加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

C#对使用AES的Java加密/解密的好奇行为

发布时间:2020-12-15 21:57:05 所属栏目:百科 来源:网络整理
导读:通过使用AES算法的字符串解密,我有一个非常奇怪的问题.我的C#应用??程序将加密数据(字符串)发送到 Java应用程序.即使我使用相同的密钥字符串,解密也会导致异常: javax.crypto.BadPaddingException:给定最终块未正确填充 ????在com.sun.crypto.provider.Cip
通过使用AES算法的字符串解密,我有一个非常奇怪的问题.我的C#应用??程序将加密数据(字符串)发送到 Java应用程序.即使我使用相同的密钥字符串,解密也会导致异常:

javax.crypto.BadPaddingException:给定最终块未正确填充
????在com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:810)

但是只有当要加密的普通输入文本的长度(在C#侧)超过1393个字符时……但如果长度等于1393个字符,或者小于1393个字符,则它可以正常工作.

这是加密的C#代码:

private static string Encrypt(string textToEncrypt,string key)
    {
        try
        {
            RijndaelManaged rijndaelCipher = new RijndaelManaged();
            rijndaelCipher.Mode = CipherMode.CBC;
            rijndaelCipher.Padding = PaddingMode.PKCS7;

            rijndaelCipher.KeySize = 0x80; // 256bit key
            rijndaelCipher.BlockSize = 0x80;
            byte[] pwdBytes = Encoding.UTF8.GetBytes(key);
            byte[] keyBytes = new byte[0x10];
            int len = pwdBytes.Length;
            if (len > keyBytes.Length)
            {
                len = keyBytes.Length;
            }
            Array.Copy(pwdBytes,keyBytes,len);
            rijndaelCipher.Key = keyBytes;
            rijndaelCipher.IV = keyBytes;
            ICryptoTransform transform = rijndaelCipher.CreateEncryptor();
            byte[] plainText = Encoding.UTF8.GetBytes(textToEncrypt);
            return Convert.ToBase64String(transform.TransformFinalBlock(plainText,plainText.Length));
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

以及用于解密的Java代码:

public static String Decrypt(String text,String key) throws Exception {
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    byte[] keyBytes = new byte[16];
    byte[] b = key.getBytes("UTF-8");
    int len = b.length;
    if (len > keyBytes.length) {
        len = keyBytes.length;
    }
    System.arraycopy(b,len);

    SecretKeySpec keySpec = new SecretKeySpec(keyBytes,"AES");
    IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);
    cipher.init(Cipher.DECRYPT_MODE,keySpec,ivSpec);

    BASE64Decoder decoder = new BASE64Decoder();
    byte[] results = cipher.doFinal(decoder.decodeBuffer(text));
    return new String(results,"UTF-8");
}

我已经尝试将BASE64Decoder从apache替换为Base64编解码器,但结果是一样的……
我会很感激任何建议或想法.谢谢.

解决方法

如果您通过网络传输密文,则应使用 message authentication code确保其完整性.在尝试解密密文之前,应验证MAC.这将防止意外破坏和恶意篡改线路上的消息.在这种情况下,它应该可以帮助您确保传输的密文与您接收的密文完全相同.

我重写了java解密端进行MAC验证.它假定MAC是使用HMACSHA1算法生成的,该算法使用与AES密码相同的密钥材料进行初始化(注意:这仅是一个示例,加密密钥和HMAC密钥在实际系统中应该是不同的)并且预先附加到密文.消息的前20个字节应该是MAC,然后是紧随其后的密文.

public static String Decrypt(String message,"AES");
    IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);

    byte[] messageBytes =  DatatypeConverter.parseBase64Binary(message);
    byte[] macBytes = new byte[20];
    byte[] ciphertext = new byte[messageBytes.length - 20];

    System.arraycopy(messageBytes,macBytes,macBytes.length);
    System.arraycopy(messageBytes,20,ciphertext,ciphertext.length);

    Mac mac = Mac.getInstance("HMACSHA1");
    mac.init(keySpec);

    verifyMac(mac.doFinal(ciphertext),macBytes);

    cipher.init(Cipher.DECRYPT_MODE,ivSpec);

    byte[] results = cipher.doFinal(ciphertext);
    return new String(results,"UTF-8");
}

private static void verifyMac(byte[] mac1,byte[] mac2) throws Exception {
    MessageDigest sha = MessageDigest.getInstance("SHA1");
    byte[] mac1_hash = sha.digest(mac1);
    sha.reset();
    byte[] mac2_hash = sha.digest(mac2);

    if(!Arrays.equals(mac1_hash,mac2_hash)){
        throw new RuntimeException("Invalid MAC");
    }

}

关于安全实践的一些注意事项.使用输入密码的UTF-8字节不会在您的密钥中提供足够的熵.如果您要使用密码作为加密密钥,则应使用密钥拉伸算法对其进行处理. PBKDF2是一个受欢迎的选择. AES密码的IV应该是随机生成的(使用加密安全的随机源),并使用密文以明文形式传输.用于初始化AES密码的密钥应该与用于MAC的密钥不同.您可以使用PBKDF2根据您提供的密码创建密钥的两倍,并将前半部分用于AES,将后半部分用于HMAC-SHA1.最后要注意的是,在验证MAC时,您应该直接验证MAC的散列而不是MAC(如上面的verifyMac方法中所示).验证MA直接暴露可能的定时攻击向量.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读