我的代码有问题,当我加密数据时,例如,在这种情况下,我用接收者的公钥加密的simmetric密钥,然后保存到文本文件,当我读取该文本文件并尝试解密它,使用接收者的私钥,我得到一个不同的密钥,因此我不能用它来解密加密的消息。
发件人代码:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
class Sender{
public static void main(String[] args) {
//infile.txt
File inFile = new File(args[0]);
//outfile.txt
File outFile = new File(args[1]);
//mykeystore.jks
File keyStoreFile = new File(args[2]);
//mykeystore info
String alias = args[3];
String password = args[4];
String storepass = args[5];
//receptor certificate
String receptorCert = args[6];
try {
//Read plain text
FileInputStream rawDataFromFile = new FileInputStream(inFile);
byte[] plainText = new byte[(int) inFile.length()];
rawDataFromFile.read(plainText);
//Create simmetric key
String key = "Bar12345Bar12345"; // 128 bit key
String initVector = "RandomInitVector"; // 16 bytes IV
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
//Encrypt plaintext
byte[] ciphertext = cipher.doFinal(plainText);
//Hash plaintext
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(plainText);
byte[] digest = md.digest();
//Encrypt simmetric key with receiver's public key
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
PublicKey receptorPublicKey = getPublicKeyFromCert(receptorCert);
rsaCipher.init(Cipher.ENCRYPT_MODE, receptorPublicKey);
byte[] simmetricKey = rsaCipher.doFinal(skeySpec.getEncoded());
//Encrypt hash with my private key
KeyStore myKeyStore = KeyStore.getInstance("JKS");
FileInputStream inStream = new FileInputStream(keyStoreFile);
myKeyStore.load(inStream, storepass.toCharArray());
PrivateKey privatekey = (PrivateKey) myKeyStore.getKey(alias, password.toCharArray());
rsaCipher.init(Cipher.ENCRYPT_MODE, privatekey);
byte[] encodedHash = rsaCipher.doFinal(digest);
//Write to outputfile
FileOutputStream outToFile = new FileOutputStream(outFile);
outToFile.write(simmetricKey);
outToFile.write(encodedHash);
outToFile.write(ciphertext);
outToFile.close();
rawDataFromFile.close();
} catch (Exception e) {
e.printStackTrace();
e.getMessage();
}
}
public static PublicKey getPublicKeyFromCert(String certLocation) {
PublicKey pub = null;
try {
InputStream inStream = new FileInputStream(certLocation);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) cf.generateCertificate(inStream);
inStream.close();
pub = (PublicKey) cert.getPublicKey();
} catch (Exception e) {
e.printStackTrace();
}
return pub;
}
}
接收者代码:
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
public class Receiver {
public static void main(String[] args) {
//Sender's out file
File inFile = new File(args[0]);
//receiver's keystore
File keyStoreFile = new File(args[1]);
//receiver's keystore info
String password = args[2];
String alias = args[3];
String storepass = args[4];
//sender's cetificate
File cert = new File(args[5]);
try {
//get Sender's out file
FileInputStream rawDataFromFile = new FileInputStream(inFile);
byte[] simmetricKey = new byte[256];
byte[] hash = new byte[256];
byte[] message;
rawDataFromFile.read(simmetricKey);
rawDataFromFile.read(hash);
int b = rawDataFromFile.available();
message = new byte[b];
rawDataFromFile.read(message);
//decrypt the simmetric key with receiver's private key
KeyStore myKeyStore = KeyStore.getInstance("JKS");
FileInputStream inStream = new FileInputStream(keyStoreFile);
myKeyStore.load(inStream, storepass.toCharArray());
PrivateKey privatekey = (PrivateKey) myKeyStore.getKey(alias, password.toCharArray());
//
Cipher deCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
deCipher.init(Cipher.DECRYPT_MODE, privatekey);
byte[] key = deCipher.doFinal(simmetricKey);
System.out.println(Base64.encodeBase64String(key));
} catch (Exception e) {
System.out.println("Error del sistema " + e);
e.printStackTrace();
}
}
}
更新
现在我可以使用接收者的私钥解密simmetric密钥。但是当我加密消息时,我不知道如何使用相同的参数创建解码器。
发件人加密纯文本的代码。
String key = "Bar12345Bar12345"; // 128 bit key
String initVector = "RandomInitVector"; // 16 bytes IV
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
System.out.println(iv.getIV());
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] ciphertext = cipher.doFinal(plainText);
接收者的解密1
SecretKeySpec keySpec = new SecretKeySpec(decryptedKeySpec, "AES");
Cipher decoder = Cipher.getInstance("AES");
decoder.init(Cipher.DECRYPT_MODE, keyspec);
byte[] original = descipher.doFinal(message);
错误:给定最后一个块未正确填充
接收者的解密2
SecretKeySpec keySpec = new SecretKeySpec(decryptedKeySpec, "AES");
Cipher decoder = Cipher.getInstance("AES/CBC/PKCS5PADDING");
decoder.init(Cipher.DECRYPT_MODE, keyspec);
byte[] original = descipher.doFinal(message);
错误:缺少参数
最终更新: 现在我的代码工作了,感谢所有的帮助。 这段代码可以从这里下载(顺便说一句,它是西班牙语,但我认为不重要):
答案 0 :(得分:6)
问题是您使用AES加密
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(" UTF-8")," AES "); 密码密码= Cipher.getInstance(" AES / CBC / PKCS5PADDING");
而要破译, 你正在使用RSA,
Cipher deCipher = Cipher.getInstance(" RSA / ECB / PKCS1Padding");
使用AES加密/解密的代码段
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
public class EncryptionDecryptionAES {
static Cipher cipher;
public static void main(String[] args) throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);
SecretKey secretKey = keyGenerator.generateKey();
cipher = Cipher.getInstance("AES");
String plainText = "AES Symmetric Encryption Decryption";
System.out.println("Plain Text Before Encryption: " + plainText);
String encryptedText = encrypt(plainText, secretKey);
System.out.println("Encrypted Text After Encryption: " + encryptedText);
String decryptedText = decrypt(encryptedText, secretKey);
System.out.println("Decrypted Text After Decryption: " + decryptedText);
}
public static String encrypt(String plainText, SecretKey secretKey)
throws Exception {
byte[] plainTextByte = plainText.getBytes();
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encryptedByte = cipher.doFinal(plainTextByte);
Base64.Encoder encoder = Base64.getEncoder();
String encryptedText = encoder.encodeToString(encryptedByte);
return encryptedText;
}
public static String decrypt(String encryptedText, SecretKey secretKey)
throws Exception {
Base64.Decoder decoder = Base64.getDecoder();
byte[] encryptedTextByte = decoder.decode(encryptedText);
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] decryptedByte = cipher.doFinal(encryptedTextByte);
String decryptedText = new String(decryptedByte);
return decryptedText;
}
}
请检查http://javapapers.com/java/java-symmetric-aes-encryption-decryption-using-jce/
答案 1 :(得分:0)
您的接收器似乎尝试读取加密对称密钥的 256字节,但我认为RSA加密密钥只有 128字节长。
所以也许它可以使用
byte[] simmetricKey = new byte[128];