Быстрое шифрование AES с Java

У меня проблема с шифрованием AES GCM на Swift. У нас есть приложение на Java, где шифрование в порядке, сервер может читать и обрабатывать данные, но мой сервер результатов не может читать. У нас есть 2 разных результата. Сначала я пытался использовать шифрование CBC и ECB, но мне сказали использовать GCM. Если кто-то понимает, что я делаю неправильно, помогите мне

Java-код:

final String airSecretKey = "Wk+Uzyyn8991w/2V5OIqiQ==";
static Cipher cipher=null;
SecretKeySpec new_key=null;
Key kateKey=null;

public void onCreate() {
    super.onCreate();
    handler = new Handler();
    if (doCryptoAes) {
        new_key = new SecretKeySpec(airSecretKey.getBytes(), "AES");
        kateKey = (Key) new SecretKeySpec(airSecretKey.getBytes(), "AES");
    }
}

void generateCliper(){
    try {
        cipher = Cipher.getInstance("AES/GCM/NoPadding");  ///", "BC
    } catch (NoSuchAlgorithmException e) {
        Log.e("AES 1", e.toString());
    } catch (NoSuchPaddingException e) {
        Log.e("AES 2", e.toString());
    } /*catch (NoSuchProviderException e) {
        Log.e("AES 3", e.toString());
    }*/
}

protected String encryptAir(String testText) {
    byte[] encodedBytes = null;
    String s_encode_result = "";
    try {
        byte[] iv = new byte[12];
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
        if (cipher==null){  
             generateCliper();  
        }
        cipher.init(Cipher.ENCRYPT_MODE, kateKey, ivParameterSpec); //new_key  //
        encodedBytes = cipher.doFinal(testText.getBytes());
        for (int i=0;i<encodedBytes.length; i++){
            s_encode_result+=getEncodeHex(encodedBytes[i]);//+" ";
        }

    } catch (Exception e) {
        Log.e(e.toString());
    }

    return "<BJSN>"+s_encode_result+"</BJSN>";
}

protected String decryptAir(String encodedText) {
    if (encodedText.length()<20) return "";

    byte[] encryptedTextByte = getConvAES(encodedText);
            //Base64.decode(encodedText, Base64.DEFAULT);


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

    } catch (InvalidAlgorithmParameterException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    }

    byte[] decryptedByte = new byte[0];
    try {
        decryptedByte = cipher.doFinal(encryptedTextByte);
    } catch (BadPaddingException e) {
        Log.e("AES 1", e.toString());
    } catch (IllegalBlockSizeException e) {
        Log.e("AES 2", e.toString());
    }
    String decryptedText = new String(decryptedByte);
  //  MainActivity.toast_str="Decrypted: "+decryptedText;
    return  decryptedText;
}

byte[] getConvAES(String textAesStr) {
    int i_len = (textAesStr.length()-13)/2;
    byte[] aesNonce= new byte[i_len];
    if (textAesStr.indexOf( "<BJSN>") == 0 &&
            textAesStr.indexOf( "</BJSN>") > 0 && i_len > 0) {
        for (int i = 3; i < i_len+3; i++) {
            String s_hex = "";
            s_hex+=textAesStr.charAt(i*2);
            s_hex+=textAesStr.charAt(i*2+1);
            int i_binary=0;
            try {
                i_binary=Integer.parseInt(s_hex, 16);
                aesNonce[i-3]=(byte) i_binary;
            } catch (Exception e) {
                aesNonce[i-3]=0;
            }
        }
    }
    return aesNonce;
}

Мой код Swift:

import CryptoKit
let key = SymmetricKey(size: .bits192)
let plain = "BSD AIR"

func cryptoDemoCombinedData() {

    let nonce = try! AES.GCM.Nonce(data: Data(base64Encoded: "fv1nixTVoYpSvpdA")!)
    let tag = Data(base64Encoded: "Wk+Uzyyn8991w/2V5OIqiQ==")!

    // Encrypt
    let sealedBox = try! AES.GCM.seal(plain.data(using: .utf8)!, using: key, nonce: nonce, authenticating: tag)

    // Decrypt
    let sealedBoxRestored = try! AES.GCM.SealedBox(combined: sealedBox.combined!)
    let decrypted = try! AES.GCM.open(sealedBoxRestored, using: key, authenticating: tag)

    print("Crypto Demo II\n••••••••••••••••••••••••••••••••••••••••••••••••••\n")
    print("Combined:\n\(sealedBox.combined!.base64EncodedString())\n")
    print("Cipher:\n\(sealedBox.ciphertext.base64EncodedString())\n")
    print("Nonce:\n\(nonce.withUnsafeBytes { Data(Array($0)).base64EncodedString() })\n")
    print("Tag:\n\(tag.base64EncodedString())\n")
    print("Decrypted:\n\(String(data: decrypted, encoding: .utf8)!)\n")
}


person Артем Хрещенюк    schedule 03.11.2020    source источник
comment
Похоже, код Swift шифрует сами данные, а не расшифровывает что-либо с сервера.   -  person OrangeDog    schedule 03.11.2020
comment
да, строка быстрого шифрования BSD AIR, потому что у меня есть результат расшифровки Java этой строки, и я пытаюсь получить тот же результат   -  person Артем Хрещенюк    schedule 03.11.2020
comment
Вы пытаетесь зашифровать что-то отдельно дважды и получаете тот же результат? Любая система, основанная на повторном использовании одноразовых номеров, не работает. Весь смысл nonce в том, что он используется только один раз. Каждый раз, когда вы шифруете один и тот же открытый текст, вы должны получать другой зашифрованный текст.   -  person OrangeDog    schedule 03.11.2020
comment
но результат Java всегда один и тот же результат Swift тоже всегда один и тот же, но результаты Java и Swift разные   -  person Артем Хрещенюк    schedule 03.11.2020
comment
Тогда код Java неверен. Похоже, ваш IV всегда равен нулю, что может быть проблемой.   -  person OrangeDog    schedule 03.11.2020
comment
Код Java работает отлично, проблема только с быстрым кодом   -  person Артем Хрещенюк    schedule 03.11.2020
comment
Результат Java всегда один и тот же - тогда он не работает   -  person OrangeDog    schedule 03.11.2020
comment
Шифрование и дешифрование AES GCM в Java   -  person OrangeDog    schedule 03.11.2020
comment
Шифрование AES GCM — без iv   -  person Артем Хрещенюк    schedule 03.11.2020
comment
Вы не можете использовать AES-GCM без IV. Если вы повторно используете IV, то он полностью сломан.   -  person OrangeDog    schedule 03.11.2020
comment
Можете ли вы предоставить нам образец вывода кода Java с ключом, используемым в вашем образце? А что произойдет, если вы попытаетесь расшифровать то, что зашифровано в Java?   -  person zaitsman    schedule 03.11.2020


Ответы (1)


Шифрование работает не так. Каждый раз, когда вы шифруете один и тот же открытый текст, вы ДОЛЖНЫ получать разные выходные данные. В GCM это достигается за счет использования каждый раз уникального случайного IV — одноразового номера (nчисла, используемого один раз).

GCM предъявляет собственные требования к IV, а именно никогда не следует повторно использовать IV, и это важно .

String airSecretKey = "Wk+Uzyyn8991w/2V5OIqiQ==";  // this key is now public so you cannot use it
SecretKey key = new SecretKeySpec(Base64.getDecoder().decode(airSecretKey), "AES");

SecureRandom secureRandom = new SecureRandom();
byte[] iv = new byte[12];
secureRandom.nextBytes(iv);
AlgorithmParameters params = new GCMParameterSpec(128, iv);

Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key, params, secureRandom);

cipher.updateAAD(...);  // if used
byte[] encrypted = cipher.doFinal(plaintext);

Версия Swift должна выполнять те же операции. Java генерирует тег и добавляет его к зашифрованному тексту. Похоже, что в Swift вам нужно обрабатывать это вручную.

person OrangeDog    schedule 03.11.2020
comment
Можем ли мы связаться в каком-нибудь мессенджере? - person Артем Хрещенюк; 04.11.2020
comment
@АртемХрещенюк Вы можете общаться здесь - person Rob; 05.11.2020