2

圧縮/解凍を使用したAES暗号化/復号化が正しく機能していることを確認しようとしている以下のテストがあります。暗号化/復号化のみのテストと圧縮/解凍のみのテストがあり、個別に正しく機能することはわかっていますが、何らかの理由でそれらを組み合わせると、解凍後にIVが台無しになります。私は立ち往生していて、他に何を探すべきかわかりません、誰かが何か提案や助けを提供できますか?さらにコードを投稿する必要がある場合はお知らせください。重要なものを入れたと思います。

コンテキスト:私がやろうとしているのは、機密データを取得し、それをAESで暗号化し、AESキーをRSA公開キーで暗号化してから、これら2つのデータを圧縮してネットワーク経由で送信できるようにすることです。次に、もう一方の端でデータを解凍し、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;      
}
4

2 に答える 2

2

OpenPGPに似た暗号システムを実装しようとしています。つまり、対称鍵を使用して任意の量のデータを暗号化し、この鍵(および暗号化されたデータ)を受信者と安全に共有する必要があります。

結果として、BouncyCastleチームが提供するJavaOpenPGPライブラリの使用を検討することをお勧めします。

彼らのライセンスは非常に寛容です。ただし、それらのドキュメントは悪名高いほど貧弱であるため、目標を達成する方法を確認するには、多くの例をGoogleで検索する必要があります。

于 2013-01-14T12:07:50.640 に答える
0

まず、バイトバッファの一部を区切るために文字列区切り文字を使用しないでください。データに区切り文字が含まれていると、問題が発生します。

TLV構造について読むことをお勧めします!

これがトランスポートデータの簡単な実装です!

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;
}
}
于 2013-01-08T19:14:33.530 に答える