2012-08-13 149 views
0

我下面this tutorial使用3DES加密,我需要作出密码设置一些变化,所以这里是我的代码:TripleDes的加密错误

public class TripleDES { 

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/PKCS7Padding"; 
private final SecretKeySpec keySpec; 
private final static String LOG = "TripleDES"; 

public TripleDES(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); 
    key = addParity(key); 
    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(String message) throws GeneralSecurityException, UnsupportedEncodingException { 
    byte[] unencrypted = message.getBytes("UTF8"); 
    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); 
} 

// Takes a 7-byte quantity and returns a valid 8-byte DES key. 
// The input and output bytes are big-endian, where the most significant 
// byte is in element 0. 
public static byte[] addParity(byte[] in) { 
    byte[] result = new byte[8]; 

    // Keeps track of the bit position in the result 
    int resultIx = 1; 

    // Used to keep track of the number of 1 bits in each 7-bit chunk 
    int bitCount = 0; 

    // Process each of the 56 bits 
    for (int i = 0; i < 56; i++) { 
     // Get the bit at bit position i 
     boolean bit = (in[6 - i/8] & (1 << (i % 8))) > 0; 

     // If set, set the corresponding bit in the result 
     if (bit) { 
      result[7 - resultIx/8] |= (1 << (resultIx % 8)) & 0xFF; 
      bitCount++; 
     } 

     // Set the parity bit after every 7 bits 
     if ((i + 1) % 7 == 0) { 
      if (bitCount % 2 == 0) { 
       // Set low-order bit (parity bit) if bit count is even 
       result[7 - resultIx/8] |= 1; 
      } 
      resultIx++; 
      bitCount = 0; 
     } 
     resultIx++; 
    } 

    Log.d(LOG, "result: " + result); 
    return result; 
} 
} 

但我在这一行越来越InvalidKeyException异常:

cipher.init(mode, keySpec); 

的logcat:

W/System.err(758): java.security.InvalidKeyException: src.length=8 srcPos=8 dst.length=8 dstPos=0 length=8 
W/System.err(758): at org.bouncycastle.jce.provider.JCEBlockCipher.engineInit(JCEBlockCipher.java:584) 
W/System.err(758): at org.bouncycastle.jce.provider.JCEBlockCipher.engineInit(JCEBlockCipher.java:631) 
W/System.err(758): at javax.crypto.Cipher.init(Cipher.java:511) 
W/System.err(758): at javax.crypto.Cipher.init(Cipher.java:471) 

我在encrytion新的,所以我PROBA bly忽略了一些东西,但我找不到它是什么。任何帮助表示赞赏...

+0

您能不能告诉我们cipher.init ()? – KingCronus 2012-08-13 08:43:24

+0

这是在doCipher? – yahya 2012-08-13 08:45:43

回答

0

我找到了解决方案,通过改变这些行:

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

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

到这些:

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); 
byte[] keyBytes = GetKeyAsBytes(key); 
keySpec = new SecretKeySpec(keyBytes, "DESede"); 

而GetKeyAsBytes方法是这样的:

public byte[] GetKeyAsBytes(String key) { 
    byte[] keyBytes = new byte[24]; // a Triple DES key is a byte[24] array 

    for (int i = 0; i < key.length() && i < keyBytes.length; i++) 
     keyBytes[i] = (byte) key.charAt(i); 

    return keyBytes; 
} 
0

三重DES需要一个24字节的密钥,而不是一个8字节的密钥。

+0

我删除了这一行:key = addParity(key);现在它给我错误的解码javax.crypto.BadPaddingException:垫块损坏 – yahya 2012-08-13 09:20:57

+0

哪个安全提供商提供DESede/ECB/PKCS7Padding? ((我的股票JDK7似乎不支持它。)它是否与'“DESede/CBC/NoPadding”'一起工作? – martijno 2012-08-13 10:15:49

+0

BouncyCastleProvider()...我现在关注这个页面:http://www.java2s但是我想我需要找到一种方法来让我的关键词在这个页面上显示,你能告诉我怎么做吗? – yahya 2012-08-13 11:02:22