2016-07-22 31 views
5

Próbuję zaszyfrować blokadę ISO-0 przy użyciu nazwy kodowej BouncyCastle lib. Metody I wykorzystać do osiągnięcia tego celu jest następująca:Dane nie bloku rozmiar wyrównany w kodowej nazwa BouncyCastle (bez wypełniania)

private static byte[] performEncrypt(byte[] key, String plainText, boolean padding) { 
    byte[] ptBytes = plainText.getBytes(); 

    BufferedBlockCipher cipher; 
    if (padding) { 
     cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new DESedeEngine())); 
    } else { 
     cipher = new BufferedBlockCipher(new CBCBlockCipher(new DESedeEngine())); 
    } 
    cipher.init(true, new KeyParameter(key)); 
    byte[] rv = new byte[cipher.getOutputSize(ptBytes.length)]; 
    int oLen = cipher.processBytes(ptBytes, 0, ptBytes.length, rv, 0); 
    try { 
     cipher.doFinal(rv, oLen); 
    } catch (CryptoException ce) { 
     LoggingUtil.error(TAG, ce, "Unexpected Exception"); 
    } 
    return rv; 
} 

private static String createIso0PinBlock(String pin, String number) { 
    ... 
} 

private static String getPaddedData(String data, byte padCharacter) { 
    String paddedData = ByteUtil.pad(data, (char) padCharacter, 8).toString(); 
    return paddedData; 
} 

public static String createPinBlockAndEncrypt(String pin, String number) { 
    LoggingUtil.debug("SecurityUtil", "CREAT PIN BLOCK AND ENCRYPT.. PIN: " + pin + " NUMBER: " + number); 
    String pb = createIso0PinBlock(pin, number.substring(0, number.length() - 1)); 
    LoggingUtil.debug("SecurityUtil", "PINBLOCK: " + pb); 
    String padded = getPaddedData(pb, (byte) 0x00); 
    LoggingUtil.debug("SecurityUtil", "PADDED: " + padded); 
    byte[] encrypted = performEncrypt(Hex.decode(KEY.getBytes()), new String(ByteUtil.hex2byte(padded)), false); 
    return ByteUtil.byte2hex(encrypted); 
} 

W ByteUtil:

public static StringBuilder pad(String data, char padCharacter, int multiplier) { 
    StringBuilder text = new StringBuilder(); 
    text.append(data); 
    while (text.length() % multiplier != 0) { 
     text.append(padCharacter); 
    } 
    return text; 
} 

Aby zapewnić wyjścia przykład log:

[SecurityUtil] CREAT PIN BLOCK AND ENCRYPT.. PIN: 2255 NUMBER: 6284734104205417486 
[SecurityUtil] PINBLOCK: 042214FBDFABE8B7 
[SecurityUtil] PADDED: 042214FBDFABE8B7 

gdy ten za pomocą metody public static void main , działa zgodnie z oczekiwaniami, jednak gdy buduję to dla Androida przez Codenameone, pojawia się następujący błąd w kodzie logcat:

org.bouncycastle.crypto.DataLengthException: data not block size aligned 
org.bouncycastle.crypto.BufferedBlockCipher.doFinal(BufferedBlockCipher.java:275) 

Pomimo, że wyściełany blok śrubowy ma 16 długości (wielokrotność 8).

Każda pomoc dotycząca tego problemu zostanie doceniona.

Odpowiedz

2

Szyfrowanie działa na binarnych danych, a PinBlock jest binarny, więc miej to w ten sposób.

Dzwoniąc performEncrypt(..) konwertować hex zakodowane PinBlock na sznurku z new String(ByteUtil.hex2byte(padded)), a wewnątrz performEncrypt(...) przekonwertować je do tablicy bajtów z byte[] ptBytes = plainText.getBytes();. Problem polega na tym, że nie wszystkie sekwencje bajtów mogą być odwzorowane prawidłowo iz powrotem przez ciąg znaków, a może skończyć się z różnych danych i nawet różnej długości itp take a look here

Zmień swój podpis ty performEncrypt(..) do:

private static byte[] performEncrypt(byte[] key, byte[] plainText, boolean padding) { 

i unikaj konwertowania za pomocą ciągu znaków.

+0

Świetna odpowiedź. Uniknęłabym używania Strings dla danych binarnych w Codename One, kiedy mapujemy Strings na natywne struny, np. na iOS i mogą mieć niewielkie rozbieżności w zachowaniu w niektórych skrajnych przypadkach. Na przykład. wystąpił problem podczas integrowania obsługi zip https://www.codenameone.com/blog/zip-and-toast.html –