Получение другого результата (зашифрованного текста) при использовании AES в Java и golang

Я пытаюсь воспроизвести код Java для шифрования AES в Golang. Однако я не получаю такой же результат в golang

Я пробовал ниже код:

Код Java:

package EncryptionTest;

import java.security.Key;
import java.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

public class EncryptionDecryptionAES {

    static Cipher cipher;

    public static void main(String[] args) throws Exception {
        Key secretKey;
        secretKey = (Key)new SecretKeySpec("0123456789012345".getBytes(), "AES");
        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, Key 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, Key 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;
    }
}

Вывод кода Java: Обычный текст до шифрования: Расшифровка симметричного шифрования AES Зашифрованный текст после шифрования: vSmrgH3qU+qEq+3ui0YvwCa6PDBcMyhgOlbh3+zzM+cON6feLk2u1iPW7lITD3vn Расшифрованный текст после расшифровки: Расшифровка симметричного шифрования AES

Код Golang:

package main

import (
    "crypto/aes"
    "crypto/cipher"
    "encoding/base64"
    "fmt"
)

const NONCESIZE = 12

func main() {
    key := []byte("0123456789012345")
    plaintext := []byte("AES Symmetric Encryption Decryption")
    block, err := aes.NewCipher(key)
    if err != nil {
        panic(err.Error())
    }
    nonce := make([]byte, NONCESIZE)
    aesgcm, err := cipher.NewGCM(block)
    if err != nil {
        panic(err.Error())
    }
    ciphertext := aesgcm.Seal(nil, nonce, plaintext, nil)
    fmt.Println("Encrypted Text is : ", base64.StdEncoding.EncodeToString(ciphertext))

}

Вывод кода Golang: Зашифрованный текст: 7UMh49c5Wqb2BzlttKBEnq5g4fxMK9oJs1EUDIgWzVwlY28k+qd/oFG9SJckBsaX6DHp


person Prashant Gupta    schedule 27.03.2019    source источник
comment
getBytes в Java не является детерминированным, а зависит от кодировки по умолчанию.   -  person Volker    schedule 27.03.2019
comment
AES использует случайный начальный вектор для шифрования. Каждый вызов генерирует случайный начальный вектор, и это приводит к разному зашифрованному тексту.   -  person Dogushan KAYA    schedule 27.03.2019
comment
@DogushanKAYA: код, который я вставил сюда, генерирует тот же зашифрованный текст.   -  person Prashant Gupta    schedule 27.03.2019


Ответы (1)


В коде go вы используете AES в режиме GCM с 12 нулевыми байтами в качестве IV, но в коде Java вы используете режим AES по умолчанию, который отличается в разных версиях Java.

Используя режим GCM (предоставленный в BouncyCastle) и установив тот же IV (12 нулевых байтов), я получил тот же результат:

package EncryptionTest;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.security.Key;
import java.security.Security;
import java.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class EncryptionDecryptionAES {

    static Cipher cipher;

    public static void main(String[] args) throws Exception {
        Security.addProvider(new BouncyCastleProvider());


        Key secretKey;
        secretKey = (Key)new SecretKeySpec("0123456789012345".getBytes(), "AES");

        cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");

        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, Key secretKey) throws Exception {
        byte[] plainTextByte = plainText.getBytes();


        byte[] iv = new byte[12];
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);

        byte[] encryptedByte = cipher.doFinal(plainTextByte);
        Base64.Encoder encoder = Base64.getEncoder();
        String encryptedText = encoder.encodeToString(encryptedByte);
        return encryptedText;
    }

    public static String decrypt(String encryptedText, Key secretKey) throws Exception {
        Base64.Decoder decoder = Base64.getDecoder();
        byte[] encryptedTextByte = decoder.decode(encryptedText);

        byte[] iv = new byte[12];
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);

        byte[] decryptedByte = cipher.doFinal(encryptedTextByte);
        String decryptedText = new String(decryptedByte);
        return decryptedText;
    }
}

Выход:

Plain Text Before Encryption: AES Symmetric Encryption Decryption
Encrypted Text After Encryption: 7UMh49c5Wqb2BzlttKBEnq5g4fxMK9oJs1EUDIgWzVwlY28k+qd/oFG9SJckBsaX6DHp
Decrypted Text After Decryption: AES Symmetric Encryption Decryption
person Hamidreza Kalantari    schedule 27.03.2019
comment
Здесь я хочу знать, что такое режим по умолчанию, который использует мой код Java, и как воспроизвести его в golang. - person Prashant Gupta; 27.03.2019
comment
@PrashantGupta полагаться на режим по умолчанию рискованно. Вы должны установить это явно. Как я уже сказал, вы можете использовать GCM в golang и java, но если вы не хотите использовать надувной замок, вы можете использовать режим CBC на обоих языках. - person Hamidreza Kalantari; 27.03.2019