2013-10-17 10 views
9

Potrzebuję zaszyfrować z pewnością ciąg od strony klienta (JavaScript) i odszyfrować od strony serwera (Java), więc znalazłem CryptoJS i napisałem kod z tymi samymi parametrami/konfiguracją mi Kod Java, ale wynik jest zawsze inny, czy masz jakiś pomysł lub co się stanie?Różne szyfrowanie wyjściowe zarówno CryptoJS, jak i Java Code

jestem użycie CBC z NoPadding

CryptoJS

http://jsfiddle.net/Soldier/gCHAG/

<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"> 
</script> 
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/pad-nopadding-min.js"></script> 
<script> 

    function padString(source) { 
     var paddingChar = ' '; 
     var size = 16; 
     var x = source.length % size; 
     var padLength = size - x; 

     for (var i = 0; i < padLength; i++) source += paddingChar; 

     return source; 
    } 

    var key = CryptoJS.enc.Hex.parse('abcdef'); 
    var iv = CryptoJS.enc.Hex.parse('fedcba'); 
    var message = "soldier"; 
    var padMsg = padString(message); 

    var encrypted = CryptoJS.AES.encrypt(padMsg, key, { iv: iv, padding: CryptoJS.pad.NoPadding, mode: CryptoJS.mode.CBC}); 

    console.log("Encrypted: "+encrypted); 
    console.log("Encrypted text: "+encrypted.ciphertext); 

</script> 

kod Java

import java.security.Key; 
import javax.crypto.Cipher; 
import javax.crypto.spec.IvParameterSpec; 
import javax.crypto.spec.SecretKeySpec; 
import sun.misc.*; 

public class AesCipher { 

    private static final String algorithm = "AES/CBC/NoPadding"; 

    private static final byte[] keyValue = new byte[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; 
    private static final byte[] ivValue = new byte[] { 'f', 'e', 'd', 'c', 'b', 'a', '9', '8', '7', '6', '5', '4', '3', '2', '1', '0' }; 

    private static final IvParameterSpec ivspec = new IvParameterSpec(ivValue); 
    private static final SecretKeySpec keyspec = new SecretKeySpec(keyValue, "AES"); 

    final protected static char[] hexArray = "ABCDEF".toCharArray(); 

    public static String encrypt(String Data) throws Exception { 
     Cipher c = Cipher.getInstance(algorithm); 
     c.init(Cipher.ENCRYPT_MODE, keyspec, ivspec); 
     byte[] encVal = c.doFinal(Data.getBytes()); 
     String encryptedValue = new BASE64Encoder().encode(encVal); 
     return encryptedValue; 
    } 

    public static String decrypt(String encryptedData) throws Exception { 
     Cipher c = Cipher.getInstance(algorithm); 
     c.init(Cipher.DECRYPT_MODE, keyspec, ivspec); 
     byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData); 
     byte[] decValue = c.doFinal(decordedValue); 
     String decryptedValue = new String(decValue); 
     return decryptedValue; 
    } 

    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); 
    } 

    private static String padString(String source) { 
     char paddingChar = ' '; 
     int size = 16; 
     int x = source.length() % size; 
     int padLength = size - x; 

     for (int i = 0; i < padLength; i++) 
     { 
      source += paddingChar; 
     } 
     return source; 
     } 

    public static void main(String[] args) throws Exception { 

     String password = "soldier"; 
     String passwordEnc = AesCipher.encrypt(padString(password)); 
     String passwordDec = AesCipher.decrypt(passwordEnc); 

     System.out.println("Plain Text : " + password); 
     System.out.println("Encrypted Text : " + passwordEnc); 
     System.out.println("Decrypted Text : " + passwordDec); 
    } 

} 

oryginalny ciąg:

soldier 

Wyjście z CryptoJS:

Encrypted: VNzZNKJTqfRbM7zO/M4cDQ== 
Encrypted Hex: 54dcd934a253a9f45b33bccefcce1c0d 

Wyjście z kodu Java:

Encrypted: j6dSmg2lfjY2RpN91GNgNw== 
Encrypted Hex: 6a3664536d67326c666a593252704e3931474e674e773d3d 

ciąg base64 szyfrowane ma taką samą długość, ale nie hex. Jeśli umieściłem wynik wyjściowy CryptoJS w kodzie Java, odszyfrowanie jest niepoprawne.

Pozdrawiam,

Odpowiedz

7

Problem polega na tym, że Twój klucz wejściowy jest niespójny.

  • CryptoJS.enc.Hex.parse('abcdef') czyta wejście jako ciąg bajtów wyrażona jako dwucyfrowych wartości hex: 01, 23, 45 itp

  • macierzy Java określa bajt wartości użyciu wartości kodowania znaków postaci. Tak więc, sekwencja bajtów (w hex) to: 30 (dziesiętnie 48, kod ASCII dla '0'), następnie 31 (dziesiętnie 49, kod ASCII dla '1') itd

Można zrobić JavaScript zgodne do realizacji Java przy użyciu CryptoJS.enc.Latin1.parse który będzie odczytany w poszczególnych wartości znakowych i wykorzystać je jako wartości bajtów: http://jsfiddle.net/gCHAG/1/ (to daje ten sam j6dSm... wyjście)

Jednakże, prawdopodobnie chcesz, każda cyfra będzie własny bajt. Aby to zrobić, musisz zmienić obie implementacje.

Java:

// use hex literals, not characters 
byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; 
// array values: 0x00, 0x01, 0x02, etc 

JavaScript:

// remember each bytes is two digits wide 
CryptoJS.enc.Hex.parse('000102030405060708090a0b0c0d0e0f') 
// array values: 0x00, 0x01, 0x02, etc 
+0

Działa dobrze, bardzo dziękuję :) – SoldierCorp

1

Znak „0” nie jest taka sama, jak wartość hex 0. Klawisz CryptoJS najprawdopodobniej inny niż klucz Java, ponieważ jesteś instancji je jako różne typy obiektów. Wydrukuj klucze/IV w obu językach po ich utworzeniu i porównaniu.

EDYCJA: To powiedziawszy, prawdopodobnie zostanie przeniesione do StackOverflow, ponieważ pytania dotyczące konkretnych bibliotek kryptograficznych nie są tutaj tematem.

+0

Tak, przepraszam . Edycja teraz. – pg1989

0

Bardzo użytecznym przykładem SoldierCorp, dziękuję!

kilka rzeczy do poprawy przykład:

  • Metoda padString nie obsługuje UTF8 i zamiast ustalania tej metody pozwala usunąć go i użyć standardowego wyściółkę

w javascript wymienić na

padding: CryptoJS.pad.Pkcs7 

w java wymień na

klucz z dowolnej frazy strun
  • Generowanie (za IV mogą być takie same)

w javascript wymienić na

var key = CryptoJS.MD5("Secret Passphrase"); 

w java wymienić na

byte[] keyValue = org.apache.commons.codec.digest.DigestUtils.md5("Secret Passphrase"); 
+0

Nie sądzę, że dobrym pomysłem jest użycie MD5 do wyprowadzenia klucza. Lepiej jest używać PBKDF2. Dobrze, że CryptoJS i Java zarówno natywnie obsługują PBKDF2. –