我在下面进行了此测试,我正在尝试验证我的AES加密/解密与压缩/解压缩是否正常工作。我只测试加密/解密和仅压缩/解压缩的测试,我个人知道它们正常工作,但由于某些原因,当我将它们组合起来时,IV在解压缩后被搞砸了。我被困住了,不知道还有什么可以寻找,有人可以提供任何建议或帮助吗?如果我需要发布更多代码,请告诉我。我想我包括了重要的东西。
对于上下文:我要做的是获取一些敏感数据,使用AES加密它,使用RSA公钥加密AES密钥,然后压缩这两个数据,以便通过网络发送它们。然后在另一端我要解压缩数据,使用RSA私钥解密AES密钥,然后使用它来解密数据。如果还有另一种方法可以实现这一目标,那么我就不会把自己写成一切。如果您建议使用图书馆,请仅建议我可以在商业产品中使用的图书馆。
@Test
public void testEncryptionDecryptionProcesses() throws SSHException {
SSHKey key1 = generateKeyPair();
UnencryptedData data = new UnencryptedData();
data.setUserName("hardy");
data.setHashedPassword("somepassword");
data.setRequest("eat");
data.setResponse("");
data.setTimestamp(new Timestamp(new Date().getTime()).toString());
data.setPublicKeyMod(key1.getPublicMod().toString());
data.setPublicKey(key1.getPublicKey().toString());
byte[] bytes = encryptAndCompress(data, key1);
assertTrue(bytes != null);
assertTrue(bytes.length > 0);
UnencryptedData decryptedData = decompressAndDecrypt(bytes, key1);
assertEquals(data.getDataForEncryption(), decryptedData.getDataForEncryption());
}
public static byte[] encryptAndCompress(UnencryptedData data, SSHKey sshKey) {
byte[] results = null;
try {
byte[] aesKey = createKeyForAES(AES_BIT_LENGTH);
//this should use the servers public key so that only the server can decrypt it
//gather data, get a digest, encrypt the data
UnencryptedData digestedData = createDigest(data);
//encrypt it
EncryptedData toCompress = encryptDataAES(digestedData, aesKey);
String encryptedAESKey = encryptKey(sshKey, aesKey);
toCompress.setEncryptedAESKey(encryptedAESKey);
//compress it
byte[] compressed = compressString(toCompress.getDataForCompression());
//return the compressed and encrypted data.
results = compressed;
} catch(SSHException e) {
Log.e("SSHFunctions.encryption", "Unable to run the encryption/compression process on the data");
} catch (UnsupportedEncodingException e) {
Log.e("SSHFunctions.encryption", "Charset not supported");
}
return results;
}
public static UnencryptedData decompressAndDecrypt(byte[] data, SSHKey sshKey) {
UnencryptedData results = null;
try {
//take the data and decompress it, should result in encryptedData|encryptedAESKey
byte[] decompressed = decompressString(data);
String decompressedStr = new String(decompressed, CHAR_SET);
String[] decompressedArr = decompressedStr.split(SPLIT_STRING);
//using the users private key decrypt the data
byte[] decryptedKey = decryptKey(sshKey, decompressedArr[1]);
EncryptedData encryptedData = new EncryptedData();
encryptedData.setAesEncryptedData(decompressedArr[0].getBytes(CHAR_SET));
encryptedData.setIV(decompressedArr[2].getBytes(CHAR_SET)); //TODO: this doesn't seem to decompress correctly
//create a digest from the decrypted data and compare it with the digest that was included.
UnencryptedData decryptedDate = decryptDataAES(encryptedData, decryptedKey);
if(validDigest(decryptedDate)) {
results = decryptedDate;
}
//if equal return the data, if not equal return null
} catch(Exception e) {
Log.e("SSHFunctions.decryption", "Unable to run the uncompress/decrypt process on the data");
}
return results;
}
public static byte[] decompressString(byte[] toDecompress) {
ByteArrayInputStream bis = new ByteArrayInputStream(toDecompress);
byte[] uncompressed;
try {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
GZIPInputStream is = new GZIPInputStream(bis);
byte[] tmp = new byte[256];
while (true) {
int r = is.read(tmp);
if (r < 0) {
break;
}
buffer.write(tmp, 0, r);
}
is.close();
uncompressed = buffer.toByteArray();
try {
bis.close();
} catch (IOException e) {
;
}
try {
buffer.close();
} catch (IOException e) {
;
}
} catch(IOException e) {
uncompressed = null;
Log.e("Zipfunctions.decompress", "Unable to decompress");
}
return uncompressed;
}
public static byte[] compressString(byte[] toCompress) {
byte[] toCompressBytes = toCompress;
byte[] compressed;
ByteArrayOutputStream bos = new ByteArrayOutputStream(toCompressBytes.length);
try {
GZIPOutputStream compressor = new GZIPOutputStream(bos);
compressor.write(toCompressBytes, 0, toCompress.length);
compressor.close();
compressed = bos.toByteArray();
try {
bos.close();
} catch(IOException e) {
;
}
} catch(IOException e) {
compressed = null;
Log.e("ZipFunctions.compress", "Unable to compress data");
}
return compressed;
}
答案 0 :(得分:2)
您正在尝试实施类似于OpenPGP的加密系统。也就是说,您希望使用对称密钥加密任意数量的数据,并与收件人安全地共享此密钥(以及加密数据)。
因此,我建议您考虑使用Java OpenPGP库provided by the BouncyCastle team。
他们的执照是very permissive。但是,他们的文档很差,因此您需要通过Google的许多示例来了解如何实现目标。
答案 1 :(得分:0)
首先,您不应该使用字符串分隔符来分隔字节缓冲区的各个部分。如果您的数据中存在分隔符,则会导致问题。
我建议你阅读TLV structure!
以下是传输数据的简单实现!
class TransportData {
private byte[] iv;
private byte[] aesKey;
private byte[] encryptedData;
public TransportData() {
}
public TransportData(byte[] iv, byte[] aesKey, byte[] encryptedData) {
this.iv = iv;
this.aesKey = aesKey;
this.encryptedData = encryptedData;
}
public byte[] encode() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeInt(iv.length);
dos.write(iv);
dos.writeInt(aesKey.length);
dos.write(aesKey);
dos.writeInt(encryptedData.length);
dos.write(encryptedData);
dos.close();
return baos.toByteArray();
}
public void decode(byte[] buffer) throws IOException {
ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
DataInputStream dis = new DataInputStream(bais);
iv = new byte[dis.readInt()];
dis.read(iv);
aesKey = new byte[dis.readInt()];
dis.read(aesKey);
encryptedData = new byte[dis.readInt()];
dis.read(encryptedData);
dis.close();
}
public byte[] getAesKey() {
return aesKey;
}
public byte[] getEncryptedData() {
return encryptedData;
}
public byte[] getIv() {
return iv;
}
}