2017-02-15 10 views
1

Я написал две функции для расшифровки и шифрования сообщений на C# и Javascript, но мне это нужно и в Java, и я не могу заставить его работать так же, как и в предыдущих.Воспроизведение метода шифрования в Java

JS метод шифрования:

this.aesEncrypt = function (encryptedMessage) { 
    var key = CryptoJS.enc.Utf8.parse("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); 
    var initialVector = CryptoJS.enc.Utf8.parse("xxxxxxxxxxxxxxxx"); 
    var encryptedText = CryptoJS.AES.encrypt(encryptedMessage, key, 
    { 
     iv: initialVector, 
     mode: CryptoJS.mode.CBC, 
     padding: CryptoJS.pad.Pkcs7 
    }); 
    return encryptedText.toString().hexEncode(); 
} 
String.prototype.hexEncode = function() { 
    var hex, i; 

    var result = ""; 
    for (i = 0; i < this.length; i++) { 
     hex = this.charCodeAt(i).toString(16); 
     result += ("0" + hex).slice(-2); 
    } 

    return result; 
} 

C# метод дешифровки:

private static string AesDecrypt(string encryptedMessage) 
{ 
    try 
    { 
     var temp = FromHex(encryptedMessage); 
     var encryptedBytes = Convert.FromBase64String(Encoding.ASCII.GetString(temp)); 
     var aes = new AesCryptoServiceProvider 
     { 
      BlockSize = 128, 
      KeySize = 256, 
      Mode = CipherMode.CBC, 
      Padding = PaddingMode.PKCS7, 
      Key = Encoding.UTF8.GetBytes("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"), 
      IV = Encoding.UTF8.GetBytes("xxxxxxxxxxxxxxxx") 
     }; 
     var crypto = aes.CreateDecryptor(aes.Key, aes.IV); 
     var secret = crypto.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length); 
     crypto.Dispose(); 
     return Encoding.ASCII.GetString(secret); 
    } 
    catch (Exception) 
    { 
     return null; 
    } 
} 

public static byte[] FromHex(string hex) 
{ 
    hex = hex.Replace("-", ""); 
    var raw = new byte[hex.Length/2]; 
    for (var i = 0; i < raw.Length; i++) 
    { 
     raw[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16); 
    } 
    return raw; 
} 

Java метод шифрования:

public static String toHex(String arg) { 
    return String.format("%x", new BigInteger(1, arg.getBytes())); 
} 
public static String AesEncrypt(String encryptedMessage){ 
    try { 
     IvParameterSpec initialVector = new IvParameterSpec("xxxxxxxxxxxxxxxx".getBytes("UTF-8")); 
     SecretKeySpec secretKeySpec = new SecretKeySpec("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".getBytes("UTF-8"), "AES"); 

     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, initialVector); 

     byte[] encrypted = cipher.doFinal(encryptedMessage.getBytes()); 
     StringBuilder encryptedSb = new StringBuilder(encrypted.length); 
     for (byte i : encrypted){ 
      encryptedSb.append(i); 
     } 
     return toHex(encryptedSb.toString()); 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
     return null; 
    } 
} 

Java возвращает 80 гекса-цифр после шифрования и JS возвращает 48 Hexa -digits. AFAIK Java PKCS5 padding - это то же самое, что и дополнение C# PKCS7.

Я также попытался с помощью base64 кодирование результата с использованием
http://commons.apache.org/proper/commons-codec/download_codec.cgi
, но это все-таки не это.

public static String AesEncrypt(String encryptedMessage){ 
    try { 
     IvParameterSpec initialVector = new IvParameterSpec("xxxxxxxxxxxxxxxx".getBytes("UTF-8")); 
     SecretKeySpec secretKeySpec = new SecretKeySpec("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".getBytes("UTF-8"), "AES"); 

     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, initialVector); 

     byte[] encrypted = cipher.doFinal(encryptedMessage.getBytes()); 

     byte[] base64 = Base64.encodeBase64(encrypted); 

     StringBuilder encryptedSb = new StringBuilder(base64.length); 
     for (byte i : base64){ 
      encryptedSb.append(i); 
     } 
     return toHex(encryptedSb.toString()); 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
     return null; 
    } 
} 
+0

Это просто для удовольствия? Вы в принципе никогда не хотите реализовывать свои собственные алгоритмы шифрования. – Michael

+0

Какой Java-провайдер вы используете? – Keith

+2

@ Майкл, я не реализую свой собственный алгоритм. Я использую AES CBC с PKCS7 Padding –

ответ

-1

Я забыл про кодировку Base64. Я был почти там в недавнем редактировании вопроса. Я просто забыл о Base64.encodeBase64String, который на самом деле не работал, но я взглянул на реализацию этой функции в классе Base64, и я нашел, как сделать это более явным.

public static String AesEncrypt(String encryptedMessage){ 
    try { 
     IvParameterSpec initialVector = new IvParameterSpec("xxxxxxxxxxxxxxxx".getBytes("UTF-8")); 
     SecretKeySpec secretKeySpec = new SecretKeySpec("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".getBytes("UTF-8"), "AES"); 

     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, initialVector); 

     byte[] encrypted = cipher.doFinal(encryptedMessage.getBytes()); 
     String base64 = StringUtils.newStringUtf8(Base64.encodeBase64(encrypted, false)); 

     return toHex(base64); 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
     return null; 
    } 
} 
+0

Смотрите мое сообщение ниже. Используйте «DatatypeConverter». Для преобразования кодировок имеет статические однострочные. – Keith

+0

Я не могу импортировать 'javax.xml.bind.DatatypeConverter' –

+0

Скопируйте/вставьте свой код. Это просто. – Keith

2

Независимо от любых других параметров AES работает с 16-байтовыми блоками. Заполнение PCKS # 5 в Java AES решит PCKS#7. С PCKS # 7 вы заполняете границу блока; то есть заполнение до ближайших 16 байтов.

Ваш вход UTF-8 «ABC» составляет 3 байта. Для 16 байтов потребуется (16-3) = 13 байтов заполнения. Поэтому зашифрованный текст будет иметь 16 байтов или 32 шестнадцатеричных символа.

Что все сказано, я считаю, что что-то не так с вашими преобразованиями кодирования между вашей логикой StringBuilder и toHex(). Попробуйте использовать DatatypeConverter.printHexBinary(byte[] val) для преобразования byte[] encrypted обратно в шестнадцатеричный.

+0

Вы были правы о кодировании :) –