2015-11-30 88 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”)); –