2015-11-30 85 views
-1

我需要使用通過密碼生成的自定義密鑰加密一些數據。Android加密3DES ECB

它必須是: 3DES 加密模式:ECB 填充模式:零

我無法找到任何代碼來做到這一點。任何人都可以給我一個例子嗎?

我已經試過這樣做,它告訴我下面的錯誤

ERROR: java.security.InvalidAlgorithmParameterException: expected IV length of 0 


import java.io.UnsupportedEncodingException; 
import java.security.GeneralSecurityException; 

import javax.crypto.Cipher; 
import javax.crypto.spec.DESedeKeySpec; 
import javax.crypto.spec.IvParameterSpec; 
import javax.crypto.spec.SecretKeySpec; 

public class Encryption { 

public static int MAX_KEY_LENGTH = DESedeKeySpec.DES_EDE_KEY_LEN; 
private static String ENCRYPTION_KEY_TYPE = "DESede"; 
private static String ENCRYPTION_ALGORITHM = "DESede/ECB/PKCS5Padding"; 
private final SecretKeySpec keySpec; 

public Encryption(String passphrase) { 
    byte[] key; 
    try { 
     // get bytes representation of the password 
     key = passphrase.getBytes("UTF8"); 
    } catch (UnsupportedEncodingException e) { 
     throw new IllegalArgumentException(e); 
    } 

    key = padKeyToLength(key, MAX_KEY_LENGTH); 
    keySpec = new SecretKeySpec(key, ENCRYPTION_KEY_TYPE); 
} 

// !!! - see post below 
private byte[] padKeyToLength(byte[] key, int len) { 
    byte[] newKey = new byte[len]; 
    System.arraycopy(key, 0, newKey, 0, Math.min(key.length, len)); 
    return newKey; 
} 

// standard stuff 
public byte[] encrypt(byte[] unencrypted) throws GeneralSecurityException { 
    return doCipher(unencrypted, Cipher.ENCRYPT_MODE); 
} 

public byte[] decrypt(byte[] encrypted) throws GeneralSecurityException { 
    return doCipher(encrypted, Cipher.DECRYPT_MODE); 
} 

private byte[] doCipher(byte[] original, int mode) throws GeneralSecurityException { 
    Cipher cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM); 
    // IV = 0 is yet another issue, we'll ignore it here 
    IvParameterSpec iv = new IvParameterSpec(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }); 
    cipher.init(mode, keySpec, iv); 
    return cipher.doFinal(original); 
} 
} 

編輯: 現在我都這樣了,我通過的「密語」參數我的自定義鍵(密鑰大小= 8) 的我打電話不接受加密結果(這是不正確的)。

正確的加密是一個本網站不把Algorith「TripleDes的」和模式:ECB https://www.tools4noobs.com/online_tools/encrypt/

我還不知道我在做什麼錯?

public class Encryption { 

public static int MAX_KEY_LENGTH = DESedeKeySpec.DES_EDE_KEY_LEN; 
private static String ENCRYPTION_KEY_TYPE = "DESede"; 
private static String ENCRYPTION_ALGORITHM = "DESede/ECB/NoPadding"; 
private final SecretKeySpec keySpec; 

public Encryption(String passphrase) { 
     byte[] key; 
    try { 
     // get bytes representation of the password 
     key = passphrase.getBytes("UTF8"); 
    } catch (UnsupportedEncodingException e) { 
     throw new IllegalArgumentException(e); 
    } 

    key = padKeyToLength(key, MAX_KEY_LENGTH); 
    keySpec = new SecretKeySpec(key, ENCRYPTION_KEY_TYPE); 
} 


private byte[] padKeyToLength(byte[] key, int len) { 
    byte[] newKey = new byte[len]; 
    System.arraycopy(key, 0, newKey, 0, Math.min(key.length, len)); 
    return newKey; 
} 

// standard stuff 
public byte[] encrypt(byte[] unencrypted) throws GeneralSecurityException { 
    return doCipher(unencrypted, Cipher.ENCRYPT_MODE); 
} 

public byte[] decrypt(byte[] encrypted) throws GeneralSecurityException { 
    return doCipher(encrypted, Cipher.DECRYPT_MODE); 
} 

private byte[] doCipher(byte[] original, int mode) throws GeneralSecurityException { 
    Cipher cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM); 
    int bs = cipher.getBlockSize(); 
    byte[] padded = new byte[original.length + bs - original.length % bs]; 
    System.arraycopy(original, 0, padded, 0, original.length); 
    cipher.init(mode, keySpec); 
    return cipher.doFinal(padded); 
} 
+0

你剛剛發佈了用於在互聯網上進行加密的密鑰...... – Relequestual

+0

錯誤很明顯:「期望的IV長度爲0」。 ECB模式不使用IV,但你真的不應該使用ECB。它在語義上不安全。至少在CBC模式下使用每個加密隨機IV。 IV不一定是保密的,所以你可以把它和密文一起發送,但它必須是不可預知的。 –

+0

@Relequestual我發佈的密鑰是一個樣本,它不是真正的關鍵。我不知道爲什麼有人低估了這個問題。 – Borja

回答

0

ECB模式不使用IV,這使得它成爲確定性密碼模式,這意味着它在語義上不安全。如果您仍然需要使用它,刪除IV作爲參數:

int bs = cipher.getBlockSize(); 
byte[] padded = new byte[original.length + bs - original.length % bs]; 
System.arraycopy(original, 0, padded, 0, original.length); 
cipher.init(mode, keySpec); 
return cipher.doFinal(padded); 

這會給你那麼可以加密零填充消息。這是有效的,因爲一個字節數組總是用它們中的零初始化。填充與BouncyCastle的ZeroPadding相同。如果你想要做零填充作爲PHP的mcrypt的做它,然後用

byte[] padded = new byte[original.length + (bs - original.length % bs) % bs]; 
+0

好了,現在它可以工作,但它不會像應該那樣進行加密,我認爲問題在於填充,我不能放置ZeroPading,因爲它表示它不存在,但它必須是ZeroPading。 – Borja

+0

我已經添加了填充代碼。 –

+0

用實際的代碼編輯我的問題。還沒有最終解決方案。你知道什麼是錯的嗎?謝謝你的幫助。 – Borja

0

這裏的例子代碼,我用它來加密與3DES的東西。我也爲我的secretKey使用Base64,但我想你會弄清楚這一點。

public class KeywordsCipher { 

private static final String PADDING = "DESede/ECB/NoPadding"; 
private static final String UTF_F8 = "UTF-8"; 
private static final String DE_SEDE = "DESede"; 
private String secretKey; 

{...} 

public String encrypt(String message, String secretKey) { 

    byte[] cipherText = null; 

    try { 
     final byte[] secretBase64Key = Base64.decodeBase64(secretKey); 
     final SecretKey key = new SecretKeySpec(secretBase64Key, DE_SEDE); 
     final Cipher cipher = Cipher.getInstance(PADDING); 
     cipher.init(Cipher.ENCRYPT_MODE, key); 
     final byte[] plainTextBytes = message.getBytes(); 
     cipherText = cipher.doFinal(plainTextBytes); 
    } catch (NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | NoSuchPaddingException e) { 
     throw new CipherException("Problem with encryption occured"); 
    } 

    return Hex.encodeHexString(cipherText); 
} 

public CipherKeywordModel decrypt(String keyToDecrypt, String secretKey) { 

    try { 
     byte[] message = DatatypeConverter.parseHexBinary(keyToDecrypt); 
     final byte[] secretBase64Key = Base64.decodeBase64(secretKey); 
     final SecretKey key = new SecretKeySpec(secretBase64Key, DE_SEDE); 
     final Cipher decipher = Cipher.getInstance(PADDING); 
     decipher.init(Cipher.DECRYPT_MODE, key); 
     final byte[] plainText = decipher.doFinal(message); 
     String decryptedText = new String(plainText, UTF_F8); 
    } catch (UnsupportedEncodingException | NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | NoSuchPaddingException e) { 
     throw new CipherException("Problem with encryption occured"); 
    } 
    return decryptedText; 
} 
+0

你能展示更多代碼嗎?什麼是CipherKeywordModel?我如何使用我需要使用的字符串鍵?什麼是DSLContext? – Borja

+0

嗨,我編輯了這段代碼,刪除了CipherKeywordModel和DSLContext。我用來創建一些對象和使用數據庫,但你不會需要這個。此代碼現在只使用secretKey。您可能不想使用密鑰的Base64編碼。如果是這樣,請使用最終字節[] secretBase64Key = secretKey.getBytes(Charset.forName(「UTF-8」)); –