2

Я работаю над мобильным приложением и клиентской стороной, мы используем JavaScript (kony) на стороне сервера его java. Это отлично работает для всех других устройств, кроме чипсетов Intel (ASUS Zenfone). PFB код JS для шифрованияASUS zenfone5 t00j AES 256 вопрос с расшифровкой

function encryptDataModeCBC() 
{ 
    var encData = "Test"; 
    try 
    { 
     var encText = CryptoJS.AES.encrypt(encData, "3f4c57006f7d2d9528de3c46b626df06cdc405cb0243b10ca7612d967c688744", { 
      iv: "31fd1ae51454cd55db81f1fa60a343ed", 
      mode: CryptoJS.mode.CBC, 
      padding: CryptoJS.pad.Pkcs7 
     }).ciphertext.toString(CryptoJS.enc.Base64); 
     alert ("encText => "+encText);  
     kony.print("$$$$ encText => "+encText);  
    } 
    catch (e) 
    { 
     alert(kony.i18n.getLocalizedString("technicalError"));  
    } 
} 

Здесь создание IV & секретного ключа с помощью SHA256 & SHA512 алгоритм хэширования.

PFB фрагмент кода, который мы используем на стороне сервера для расшифровки зашифрованной строки

секрет генерации ключей код

private SecretKeySpec getKey(String mode, String msgDigest, String encryptionKey, boolean is256) throws Exception { 
    byte[] key = encryptionKey.getBytes("UTF-8"); 
    MessageDigest sha = MessageDigest.getInstance(msgDigest); // This is SHA-256 
    key = sha.digest(key); 
    if (is256) { // This is true in our case. 
     key = Arrays.copyOf(key, 32); 
     this.logger.debug("Secret Key " + DigestUtils.sha256Hex(encryptionKey).substring(0, 32)); 
    } else { 
     key = Arrays.copyOf(key, 16); 
     this.logger.debug("Secret Key " + DigestUtils.sha256Hex(encryptionKey).substring(0, 16)); 
    } 
    SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); 
    String modeStr = mode.equals("ECB") ? "AES/ECB/PKCS5Padding" : "AES/CBC/PKCS5Padding"; 
    cipher = Cipher.getInstance(modeStr); 
    return secretKeySpec; 
} 

IV поколения на стороне сервера

private IvParameterSpec getIV(String uid, String pin) throws Exception { 
    String ivValue = new StringBuilder(uid).reverse().toString() + new StringBuilder(pin).reverse(); 
    byte[] key = ivValue.getBytes("UTF-8"); 
    MessageDigest sha = MessageDigest.getInstance("SHA-256"); 
    key = sha.digest(key); 
    key = Arrays.copyOf(key, 16); 
    IvParameterSpec iv = new IvParameterSpec(key); 
    return iv; 
} 

Как я уже говорил выше этого не удается в устройствах чипсета Intel. Это исключение, которое я получаю при расшифровке строки

javax.crypto.BadPaddingException: Given final block not properly padded 
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..) 
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..) 
    at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..) 
    at javax.crypto.Cipher.doFinal(DashoA13*..) 

Когда я попытался зашифровать строку «Test» Я получаю «Tn2SzI8dmgCmEvQrzdqLxw ==» в качестве зашифрованной строки, которые я использовал в ниже код Java и попытался дешифрования, где я получаю ошибку ниже

enc text => 7b9UNDI4IWNITNAQlYNP8w== 
javax.crypto.BadPaddingException: Given final block not properly padded 
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966) 
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824) 
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436) 
at javax.crypto.Cipher.doFinal(Cipher.java:2165) 
at com.ust.Encryptor.decrypt(Encryptor.java:92) 
at com.ust.Encryptor.main(Encryptor.java:113) 

Вот код JAVA, который я использовал для дешифрования

package com.ust; 

import java.io.UnsupportedEncodingException; 
import java.security.InvalidAlgorithmParameterException; 
import java.security.InvalidKeyException; 
import java.security.MessageDigest; 
import java.security.NoSuchAlgorithmException; 
import java.security.spec.InvalidKeySpecException; 
import java.util.Arrays; 
import javax.crypto.BadPaddingException; 
import javax.crypto.Cipher; 
import javax.crypto.IllegalBlockSizeException; 
import javax.crypto.NoSuchPaddingException; 
import javax.crypto.spec.IvParameterSpec; 
import javax.crypto.spec.SecretKeySpec; 
import org.apache.commons.codec.binary.Base64;  
import org.apache.commons.codec.digest.DigestUtils; 

public class Encryptor { 
    private static final String AES_PASS = "0ca763dc6b05b5230e44beb6b90e346440204b6d334b09623eafd3fcfbad6a302faca28b0994872e3fd782e7353026684b7ac9385662144e0ed1e2a8e3e14fab79059929681e3794eb97271328ecccda6dbfb3a7991ea1324615cf5908fabdf6"; // Hashed into an AES key later 
    private SecretKeySpec keyObj; 
    private Cipher cipher; 
    private IvParameterSpec ivObj; 
    final protected static char[] hexArray = "ABCDEF".toCharArray(); 


    public Encryptor() throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException { 
     // A constant IV, since CBC requires an IV but we don't really need one 

     String ivValue = new StringBuilder("astring").reverse().toString() + new StringBuilder("0ca763dc6b05b5230e44beb6b90e346440204b6d334b09623eafd3fcfbad6a302faca28b0994872e3fd782e7353026684b7ac9385662144e0ed1e2a8e3e14fab").reverse(); 
     System.out.println("ivValue => "+ivValue); 
     try { 
      byte[] ivkey = ivValue.getBytes("UTF-8"); 
      MessageDigest shaIv = MessageDigest.getInstance("SHA-256"); 
      ivkey = shaIv.digest(ivkey); 
      ivkey = Arrays.copyOf(ivkey, 16); 
      System.out.println("IV => "+bytesToHex(ivkey)); 
      this.ivObj = new IvParameterSpec(ivkey); 
     } catch (UnsupportedEncodingException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     // Create an SHA-256 256-bit hash of the key 
     byte[] key = AES_PASS.getBytes(); 
     MessageDigest sha = MessageDigest.getInstance("SHA-256"); 
     key = sha.digest(key); 
     key = Arrays.copyOf(key, 32); // Use only first 256 bit 
     System.out.println("SEC KEY => "+bytesToHex(key)); 
     this.keyObj = new SecretKeySpec(key, "AES"); 

     // Create a Cipher by specifying the following parameters 
     // a. Algorithm name - here it is AES 
     // b. Mode - here it is CBC mode 
     // c. Padding - e.g. PKCS7 or PKCS5 
     this.cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); 
    } 

    public String encrypt(String strDataToEncrypt) throws InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, NoSuchPaddingException { 
     String strCipherText = new String(); 

     this.cipher.init(Cipher.ENCRYPT_MODE, this.keyObj, this.ivObj); 

     // Encrypt the Data 
     // a. Declare/Initialize the Data. Here the data is of type String 
     // b. Convert the Input Text to Bytes 
     // c. Encrypt the bytes using doFinal method 
     byte[] byteDataToEncrypt = strDataToEncrypt.getBytes(); 

     byte[] byteCipherText = this.cipher.doFinal(byteDataToEncrypt); 

     // b64 is done differently on Android 
     strCipherText = Base64.encodeBase64String(byteCipherText); 

     return strCipherText; 
    } 

    public String decrypt(String strCipherText) throws InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, NoSuchPaddingException { 
     String strDecryptedText = new String(); 

     // Initialize the Cipher for Encryption 
     this.cipher.init(Cipher.DECRYPT_MODE, this.keyObj, this.ivObj); 

     // Decode the Base64 text 
     byte[] cipherBytes = Base64.decodeBase64(strCipherText); 

     // Decrypt the Data 
     // a. Initialize a new instance of Cipher for Decryption (normally don't reuse the same object) 
     //  Be sure to obtain the same IV bytes for CBC mode. 
     // b. Decrypt the cipher bytes using doFinal method 
     byte[] byteDecryptedText = this.cipher.doFinal(cipherBytes); 
     strDecryptedText = new String(byteDecryptedText); 

     return strDecryptedText; 
    } 
    public static String bytesToHex(byte[] bytes) { 
     char[] hexChars = new char[bytes.length * 2]; 
     int v; 
     for (int j = 0; j < bytes.length; j++) { 
      v = bytes[j] & 0xFF; 
      hexChars[j * 2] = hexArray[v >>> 4]; 
      hexChars[j * 2 + 1] = hexArray[v & 0x0F]; 
     } 
     return new String(hexChars); 
    } 

    public static void main (String args[]) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException{ 
     Encryptor aesCipher = new Encryptor(); 
     try { 
      String encText = aesCipher.encrypt("Test"); 
      System.out.println("enc text => "+encText); 
      String plaintext = aesCipher.decrypt("Tn2SzI8dmgCmEvQrzdqLxw==");//("eat6f1uCCXVqJgTNUA8BCqXSA4kG4GhKajXdkyV0TewK+jgDkbQ/lPVaevv4rW3XdSmtVyOKLVJjPw9Akeblrh+ejIv9u48n7PkRKniwfxq/URuPU7lhS/sO5JMiJ7+ufgKFvJapxhSfftCtigtDc8F6Y2lJIPEUeQeQKOVc1noeLqPFggz55hWjWvDtpYh/sG76MwLlWDM7cj+uu6ru3ImmDA7qoM4tJOWBBkfng8u20R1ZcF3gM45TgDLUdL912AE1WO+grGBGjqzTXlK2/jgu3OOsLVI0jndB49K5q3/oKJc7JEoIZb0eZJcuZ80A"); 
      System.out.println("plain text => "+plaintext); 
     } catch (InvalidKeyException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (InvalidAlgorithmParameterException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (BadPaddingException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IllegalBlockSizeException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
} 
+0

Artjom, я обновил сообщение с образцовыми кодами, которые я использовал для воспроизведения проблемы. не могли бы вы помочь мне понять, почему это происходит? – Kris

ответ

2

CryptoJS предполагает, что

  • ключ, который передается в виде строки на самом деле пароль и хэш его снова вместе со случайной солью или он будет использовать ключ, как-то, если это WordArray и
  • ХВ должны be WordArray

WordArray - внутреннее представление двоичных данных CryptoJS.

Код должен быть:

try { 
    var key = CryptoJS.enc.Hex.parse("3f4c57006f7d2d9528de3c46b626df06cdc405cb0243b10ca7612d967c688744"); 
    var iv = CryptoJS.enc.Hex.parse("31fd1ae51454cd55db81f1fa60a343ed44"); 
    var encText = CryptoJS.AES.encrypt(encData, key, { 
     iv: iv, 
     mode: CryptoJS.mode.CBC, 
     padding: CryptoJS.pad.Pkcs7 
    }).ciphertext.toString(CryptoJS.enc.Base64); 
    alert ("encText => "+encText);  
    kony.print("$$$$ encText => "+encText);  
} 
catch (e) 
{ 
    alert(kony.i18n.getLocalizedString("technicalError")); 
} 

Что-то думать о:

  • Если вы отправляете симметричный ключ от сервера к клиенту, то кто-нибудь, кто мог бы слушать получит ключ и может расшифровать зашифрованные тексты, которые вы отправляете. Это решение не обеспечивает безопасность, а скорее запутывание. Вы должны использовать TLS, который сделает соединение действительно безопасным.

  • IV должен быть непредсказуемым (читается: случайным). Не используйте статический IV, потому что это делает шифр детерминированным и, следовательно, не семантически безопасным. Злоумышленник, который наблюдает за зашифрованным текстом, может определить, когда тот же префикс сообщения был отправлен раньше. IV не секрет, поэтому вы можете отправить его вместе с зашифрованным текстом. Обычно это просто добавляется к зашифрованному тексту и разрезается перед расшифровкой.

  • Лучше аутентифицировать ваши зашифрованные тексты, чтобы атаки, подобные padding oracle attack, невозможны. Это можно сделать с помощью аутентифицированных режимов, таких как GCM или EAX, или с помощью схемы encrypt-then-MAC.

+0

Artjom, ключ & iv, который я передал как строка, уже выполняет cryptoJS.enc.hex. только для целей тестирования я сильно закодировал значение. – Kris

+0

, когда я попытался с кодом выше, я получаю encText как null. – Kris

+0

Извините, это должен был быть 'CryptJS.enc.Hex.parse' вместо' CryptJS.enc.Hex'. Я получаю зашифрованный текст 7b9UNDI4IWNITNAQlYNP8w == –

Смежные вопросы