使用Java解密3Des中的值

时间:2012-05-16 17:13:19

标签: java encryption cryptography private-key 3des

我无法解密使用3Des的第三方的值。他们给了我一个密钥,一个加密的值,使用的模式,以及解密的值应该是什么,但到目前为止,我一直无法弄清楚如何从a点到b点。我认为问题与他们给我的关键有关 - 他们说这是明文密钥,但我认为还需要以某种方式进一步改变。

以下代码是我最初尝试解释如何解密该值的示例(在这种情况下为AC9C5A46A63FC9EA)

任何见解都将不胜感激。

import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;

public class TripleDes2 {

private static final String UNICODE_FORMAT = "UTF8";
private static final String DESEDE_ENCRYPTION_SCHEME = "DESede";
private static final String CIPHER_ALG = "DESede/ECB/Nopadding"; //assuming no padding
private KeySpec ks;
private SecretKeyFactory skf;
private Cipher cipher;
private byte[] arrayBytes;
private String myEncryptionKey;
private SecretKey key;

public static void main(String args []) throws Exception {
    TripleDes2 td= new TripleDes2();

    String decrypted = td.decrypt("AC9C5A46A63FC9EA");
    System.out.println("expecting: 04286EDDFDEA6BD7");
    System.out.println("found: " + decrypted);
}

public TripleDes2() throws Exception {
    myEncryptionKey = "1032FD2CD64A9D7FA4D061F76B04BFEA";
    arrayBytes = myEncryptionKey.getBytes(UNICODE_FORMAT);
    ks = new DESedeKeySpec(arrayBytes);
    skf = SecretKeyFactory.getInstance(DESEDE_ENCRYPTION_SCHEME);

    cipher = Cipher.getInstance(CIPHER_ALG);
    key = skf.generateSecret(ks);
}

public String decrypt(String encryptedString) {
    String decryptedText=null;
    try {
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] encryptedText = encryptedString.getBytes();
        byte[] plainText = cipher.doFinal(encryptedText);
        decryptedText= new String(plainText);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return decryptedText;
}
}

2 个答案:

答案 0 :(得分:2)

你使用SecretKeyFactory等使它变得比你需要的更复杂。但主要的问题是你没有正确地转换十六进制数字。

class TripleDES
{

  private final String key;

  public static void main(String... args)
    throws Exception
  {
    TripleDES td = new TripleDES("1032FD2CD64A9D7FA4D061F76B04BFEA");
    String decrypted = td.decrypt("AC9C5A46A63FC9EA");
    System.out.println("expecting: 04286EDDFDEA6BD7");
    System.out.println("found: " + decrypted);
  }

  TripleDES(String key)
  {
    this.key = key;
  }

  public String decrypt(String input)
    throws Exception
  {
    byte[] tmp = h2b(this.key);
    byte[] key = new byte[24];
    System.arraycopy(tmp, 0, key, 0, 16);
    System.arraycopy(tmp, 0, key, 16, 8);
    Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");
    cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "DESede"));
    byte[] plaintext = cipher.doFinal(h2b(input));
    return b2h(plaintext);
  }

  private static byte[] h2b(String hex)
  {
    if ((hex.length() & 0x01) == 0x01)
      throw new IllegalArgumentException();
    byte[] bytes = new byte[hex.length() / 2];
    for (int idx = 0; idx < bytes.length; ++idx) {
      int hi = Character.digit((int) hex.charAt(idx * 2), 16);
      int lo = Character.digit((int) hex.charAt(idx * 2 + 1), 16);
      if ((hi < 0) || (lo < 0))
        throw new IllegalArgumentException();
      bytes[idx] = (byte) ((hi << 4) | lo);
    }
    return bytes;
  }

  private static String b2h(byte[] bytes)
  {
    char[] hex = new char[bytes.length * 2];
    for (int idx = 0; idx < bytes.length; ++idx) {
      int hi = (bytes[idx] & 0xF0) >>> 4;
      int lo = (bytes[idx] & 0x0F);
      hex[idx * 2] = (char) (hi < 10 ? '0' + hi : 'A' - 10 + hi);
      hex[idx * 2 + 1] = (char) (lo < 10 ? '0' + lo : 'A' - 10 + lo);
    }
    return new String(hex);
  }

}

答案 1 :(得分:0)

主要问题似乎是使用包含十六进制数据的字符串,这些数据通过getBytes()转换为字节数组。

要将十六进制字符串转换为其字节数组表示形式,您需要一个外部库,例如apache.commons.codec.binary

 myEncryptionKey = "1032FD2CD64A9D7FA4D061F76B04BFEA";
 arrayBytes = Hex.decodeHex(myEncryptionKey.toCharArray());