1

我在解密来自使用 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;
}
}
4

2 回答 2

3

您使用 等 使其变得比您需要的更复杂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);
  }

}
于 2012-05-16T17:52:27.687 回答
0

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

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

 myEncryptionKey = "1032FD2CD64A9D7FA4D061F76B04BFEA";
 arrayBytes = Hex.decodeHex(myEncryptionKey.toCharArray());
于 2012-05-16T17:43:20.577 回答