使用OpenSSL加密的方式与Java相同

时间:2015-08-14 21:08:09

标签: java encryption openssl javax.crypto

我必须使用bash脚本加密字符串,就像我使用javax.crypto.Cipher加密一样。在java我使用AES-256键,键“0123456789”。但是当我使用openssl时我不得不将“0123456789”转换为十六进制,但结果与java不一样

echo "lun01" | openssl aes-256-cbc -e -a -K 7573746f726530313233343536373839 -iv 7573746f726530313233343536373839

dpMyN7L5HI8VZEs1biQJ7g ==

爪哇:

public class CryptUtil {
    public static final String DEFAULT_KEY = "0123456789";

    private static CryptUtil instance;

    private String chiperKey;

    private CryptUtil(String chiperKey) {
        this.chiperKey = chiperKey;
    }

    public static CryptUtil getInstance() {
        if (null == instance) {
            instance = new CryptUtil(DEFAULT_KEY);
        }

        return instance;
    }

    public static CryptUtil getInstance(String cipherkey) {
        instance = new CryptUtil(cipherkey);
        return instance;
    }

    public String aesEncrypt(String plainText) {
            byte[] keyBytes = Arrays.copyOf(this.chiperKey.getBytes("ASCII"), 16);

            SecretKey key = new SecretKeySpec(keyBytes, "AES");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.ENCRYPT_MODE, key);

            byte[] cleartext = plainText.getBytes("UTF-8");
            byte[] ciphertextBytes = cipher.doFinal(cleartext);
            final char[] encodeHex = Hex.encodeHex(ciphertextBytes);

            return new String(encodeHex);

        return null;
    }

    public static void main(String[] args) {

        CryptUtil cryptUtil = CryptUtil.getInstance();
        System.out.println(cryptUtil.aesEncrypt("lun01"));
    }
}

d230b216e9d65964abd4092f5c455a21

1 个答案:

答案 0 :(得分:3)

如果无数的在线十六进制转换器不起作用,那么您只需将您在Java中使用的密钥打印为十六进制即可。 Here是关于此专长的热门搜索问题。

在您完成此操作后,您会发现它仍然无效,因为您使用的是不同的算法。

当您使用Cipher.getInstance("AES");时,它很可能默认为" AES / ECB / PKCS5Padding"这与" aes-256-cbc"不同,因为ECB和CBC是两个完全不同的modes of operation。为了防止这种含糊不清,请始终完全符合您的密码,例如:Cipher.getInstance("AES/CBC/PKCS5Padding");

然后,您在Java中生成的密钥长度只有16个字节,因此OpenSSL中的匹配密码将是" aes-128-ecb"。

正如dave_thompson_085在comment中所说的那样:

  • echo添加了您的Java代码未添加的换行符。您需要以这种方式创建明文:echo -n "lun01"。如果您在Windows上,请参阅this

  • 您的Java代码将结果输出为十六进制,因此您需要在OpenSSL中执行相同的操作。您需要删除OpenSSL命令中的-a选项以防止Base64编码,然后您可以利用其他命令行工具(如Linux上的od)将二进制输出数据转换为带od -tx1的十六进制

  • 完整命令:

    echo -n lun01 |openssl aes-128-ecb -K 30313233343536373839000000000000 |od -tx1
    

不要使用ECB模式!它没有语义安全性。您需要至少使用带有随机IV的CBC模式(检查它是否是随机的,而不仅仅是零字节)。

更好的方法是添加身份验证,例如添加带有加密然后MAC方法的HMAC标记,或者只使用GCM等经过身份验证的模式。

如果您正在使用除ECB之外的任何其他内容,那么您无法在两个版本中加密相同的内容并期望出现相同的密文。由于它是随机的,您需要在一个版本中加密并在另一个版本中解密以确保兼容性。