我正在编写一个加密和解密文本文件的程序。 我为发件人和收件人创建了2个密钥库,并使用发件人的私钥和接收者的公钥在加密部分生成了数字签名。
该文件已加密,现在我无法解密它 - 数字签名没有被验证,虽然我转移它(和其他一些参数,如IV和密钥通过配置文件),我想我正在使用CipherInputStream错误,因为没有写入输出文件,Eclipse没有显示我任何错误。
这是我的代码,解密部分是最后一个功能:
package cryptogaphy;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.KeyPair;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Base64;
import java.util.Properties;
import java.util.Scanner;
public class crypto {
public static void main(String[] args) throws Exception {
// Getting Alice's keyStore password for encrypting
Scanner reader = new Scanner(System.in);
String aliceStorePass;
System.out.println("In order to start the encryption, please enter Alice's Kestore password:");
aliceStorePass = reader.next();
System.out.println("aliceStorePass: " + aliceStorePass);
encrypt(aliceStorePass);
// Getting Bob's keyStore password for decrypting
String bobStorePass;
System.out.println("Now let's decrypt: Please enter Bob's Kestore password:");
bobStorePass = reader.next();
System.out.println("bobStorePass: " + bobStorePass);
decrypt(bobStorePass);
reader.close();
}
public static void encrypt(String storePass) throws Exception {
try {
// Generate a symmetric key
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
SecureRandom secureRandom = new SecureRandom();
int keyBitSize = 128;
keyGenerator.init(keyBitSize, secureRandom);
SecretKey symmetricKey = keyGenerator.generateKey();
Key key = symmetricKey;
System.out.println("Symmetric Key: " + key);
// Generate a random IV
SecureRandom randomSecureRandom = SecureRandom.getInstance("SHA1PRNG");
byte[] ivByte = new byte[16];
randomSecureRandom.nextBytes(ivByte);
IvParameterSpec iv = new IvParameterSpec(ivByte);
System.out.println("Random Iv: " + iv);
// Defining the data we want to encrypt
File plainData = new File("C:\\Users\\Victoria\\Desktop\\plainData.txt");
File encryptedData = new File("C:\\Users\\Victoria\\Desktop\\encryptedData.txt");
FileInputStream inputStream = new FileInputStream(plainData);
FileOutputStream outputStream = new FileOutputStream(encryptedData);
byte[] inputBytes = new byte[(int) plainData.length()];
inputStream.read(inputBytes);
inputStream.close();
// Encrypting
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, iv, SecureRandom.getInstance("SHA1PRNG"));
CipherOutputStream output = new CipherOutputStream(outputStream, cipher);
output.write(inputBytes);
output.close();
byte curIV[] = cipher.getIV();
String ivString = new String(curIV);
System.out.println("ivString: " + ivString);
// Load Alice's keyStore in order to retrieve keys
// Alice's private key will be used for computing a digital signature
// Bob's public key will be used for encrypting a symmetric key
char[] aliceStorePass = storePass.toCharArray();
char[] aliceKeypass = "aliceKey".toCharArray();
FileInputStream aliceInput = new FileInputStream("C:\\Users\\Victoria\\Desktop\\cryptography\\aliceKeystore.jks");
KeyStore aliceKeystore = KeyStore.getInstance("JKS");
aliceKeystore.load(aliceInput, aliceStorePass);
String alias = "alice";
String alias2 = "bobcert";
Key aliceKey = aliceKeystore.getKey(alias, aliceKeypass);
PublicKey bobPublicKey = null;
// retrieve Alice's private key and Bob's public key from Alice's keyStore
if (aliceKey instanceof PrivateKey) {
Certificate cert = aliceKeystore.getCertificate(alias2);
bobPublicKey = cert.getPublicKey();
new KeyPair(bobPublicKey, (PrivateKey) aliceKey);
System.out.println("Alice's private key: " + (PrivateKey) aliceKey);
}
System.out.println("Bob's public key: " + bobPublicKey);
// Encrypt the Symmetric Key with asymmetric RSA algorithm
byte[] encryptedkey = symmetricKey.getEncoded();
Cipher keyCipher = Cipher.getInstance("RSA");
keyCipher.init(Cipher.ENCRYPT_MODE, bobPublicKey );
keyCipher.doFinal(encryptedkey);
System.out.println("Asymmetric Secret Key: " + encryptedkey);
// Computing an asymmetric digital signature of the encrypted data
Signature sign = Signature.getInstance("SHA1withRSA");
sign.initSign((PrivateKey) aliceKey);
FileInputStream fis = new FileInputStream(encryptedData);
BufferedInputStream bufin = new BufferedInputStream(fis);
byte[] buffer = new byte[1024];
int len;
while ((len = bufin.read(buffer)) >= 0) {
sign.update(buffer, 0, len);
};
bufin.close();
byte[] realSig = sign.sign();
System.out.println("Signature: " + realSig);
System.out.println("ENCRYPTION COMPLETED! check your encrypted data file\n");
// Update configuration file
Properties prop = new Properties();
try {
//set the properties value
String keyString = Base64.getEncoder().encodeToString(symmetricKey.getEncoded());
String encryptedkeyString = new String(encryptedkey);
String realSigString = new String(realSig);
prop.setProperty("iv", ivString);
prop.setProperty("key", keyString);
prop.setProperty("encrypted_symmetric_key", encryptedkeyString);
prop.setProperty("signature", realSigString);
prop.setProperty("signature_algorithm", "SHA1withRSA");
//save properties to project root folder
prop.store(new FileOutputStream("C:\\Users\\Victoria\\Desktop\\cryptography\\resources\\config.properties"), null);
} catch (IOException ex) {
ex.printStackTrace();
}
} catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException | CertificateException e){
System.out.println(e);
}
}
public static void decrypt(String storePass) throws Exception {
// Load configuration file
Properties prop = new Properties();
InputStream input = new FileInputStream("C:\\Users\\Victoria\\Desktop\\cryptography\\resources\\config.properties");
prop.load(input);
// Retrieving values from configuration file
String key = prop.getProperty("key");
System.out.println("key: " + key);
String iv = prop.getProperty("iv");
System.out.println("iv: " + iv);
String stringSignature = prop.getProperty("signature");
System.out.println("signature: " + stringSignature);
// Coverting to cipher applicable parameters
byte[] keyBytes = Base64.getDecoder().decode(key);
Key newkey = new SecretKeySpec(keyBytes,0,keyBytes.length, "AES");
byte[] ivBytes = iv.getBytes();
IvParameterSpec newiv = new IvParameterSpec(ivBytes);
// Load Bob's keyStore in order to retrieve keys
// Alice's public key will be used for verifying the digital signature
// Bob's private key will be used for decrypting the data
char[] bobStorePass = storePass.toCharArray();
char[] bobKeypass = "bobKey".toCharArray();
String alias = "bob";
String alias2 = "alicecert";
FileInputStream bobInput = new FileInputStream("C:\\Users\\Victoria\\Desktop\\cryptography\\bobKeystore.jks");
KeyStore bobKeystore = KeyStore.getInstance("JKS");
bobKeystore.load(bobInput, bobStorePass);
Key bobKey = bobKeystore.getKey(alias, bobKeypass);
PublicKey alicePublicKey = null;
// retrieve Bob's private key and Alice's public key from Bob's keyStore
if (bobKey instanceof PrivateKey) {
Certificate cert = bobKeystore.getCertificate(alias2);
alicePublicKey = cert.getPublicKey();
new KeyPair(alicePublicKey, (PrivateKey) bobKey);
System.out.println("Bob's private key: " + (PrivateKey) bobKey);
}
System.out.println("Alice's public key: " + alicePublicKey);
File encryptedData = new File("C:\\Users\\Victoria\\Desktop\\encryptedData.txt");
File decryptedData = new File("C:\\Users\\Victoria\\Desktop\\decryptedData.txt");
FileInputStream inputStream = new FileInputStream(encryptedData);
byte[] inputBytes = new byte[(int) decryptedData.length()];
inputStream.read(inputBytes);
// Verify digital signature
Signature sig = Signature.getInstance("SHA1withRSA");
sig.initVerify(alicePublicKey);
BufferedInputStream bufin = new BufferedInputStream(inputStream);
byte[] buffer = new byte[1024];
int len;
while (bufin.available() != 0) {
len = bufin.read(buffer);
sig.update(buffer, 0, len);
};
byte[] sigToVerify = stringSignature.getBytes();
boolean verifies = sig.verify(sigToVerify);
System.out.println("signature verifies: " + verifies);
// Decryption
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, newkey, newiv, SecureRandom.getInstance("SHA1PRNG"));
CipherInputStream cipherInputStream = new CipherInputStream(inputStream, cipher);
FileOutputStream outputStream = new FileOutputStream(decryptedData);
// Writing the decrypted content to an output file
byte[] buff = new byte[1024 * 10];
int length;
while ((length = cipherInputStream.read(buff)) > 0) {
outputStream.write(buff, 0, length);
}
bufin.close();
outputStream.close();
cipherInputStream.close();
}
}
对不起代码的长度,任何帮助都将不胜感激!