微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

AES/GCM/NoPadding JAVA 加密与 C# 加密不匹配

如何解决AES/GCM/NoPadding JAVA 加密与 C# 加密不匹配

我在 C# 和 Java 中使用了一些加密函数,它们的输出似乎不匹配。我已经为此挣扎了几天,我想我终于可以求助于这里了。

输入字符串:“a”

这是java实现的一个片段:

CryptoAesGcmService.getInstance().encryptData("a",aes_key)

    import javax.crypto.Cipher;
    import javax.crypto.spec.GCMParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    
    import java.nio.charset.StandardCharsets;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.util.Base64;
    
    public class CryptoAesGcmService {
    
        private static CryptoAesGcmService instance;
        private static final int GCM_TAG_LENGTH = 16;
        private static final int GCM_IV_LENGTH = 12;
    
        public static CryptoAesGcmService getInstance() {
            if (instance == null) {
                instance = new CryptoAesGcmService();
            }
            return instance;
    
        }
        
        public String encryptData(String plaintext,String key) throws Exception {
            return encrypt2(plaintext,key,createGCMParameter());
        }
        
        private static String encrypt(String plaintext,String key,GCMParameterSpec gcmParameterSpec) throws Exception {
    //      return plaintext;
            try {
                byte[] plainTextByte = plaintext.getBytes(StandardCharsets.UTF_8);
                Cipher cipher = Cipher.getInstance("AES/GCM/nopadding");
                cipher.init(Cipher.ENCRYPT_MODE,createSecretKeySpec(key),gcmParameterSpec);
                byte[] cipherText = cipher.doFinal(plainTextByte);
                return Base64.getEncoder().encodetoString(cipherText);
            } catch (Exception e) {
                throw new Exception("Unexpected exception occur.",e);
            }
        }
    
        private static SecretKeySpec createSecretKeySpec(String secretKey) throws NoSuchAlgorithmException {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            md.update(secretKey.getBytes(StandardCharsets.UTF_8));
            return new SecretKeySpec(md.digest(),"AES");
        }
    
        private static GCMParameterSpec createGCMParameter() {
            return new GCMParameterSpec(GCM_TAG_LENGTH * 8,new byte[GCM_IV_LENGTH]);
        }
        
    }

输出:修复 3UhjsGLxeoCyP/cd7c7p++I=

这是 .Net 实现的一个片段:

aes.Encrypt("a",aes_key);


using System;
using System.Buffers.Binary;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;

namespace api.Class
{
    public class AESGCM
    {
        private const int KEY_BIT_SIZE = 256;
        private const int MAC_BIT_SIZE = 128;
        private const int NONCE_BIT_SIZE = 128;

        private readonly SecureRandom random;

        private static AESGCM instance;

        public static AESGCM Instance //property of this class. Create an instance if it is not created yet
        {
            get
            {
                if (instance == null)
                    instance = new AESGCM();
                return instance;
            }
        }

        public AESGCM()
        {
            random = new SecureRandom();
        }

        //encrypt with strings
        public string Encrypt(string text,string key,byte[] nonSecretPayload = null)
        {
            if (string.IsNullOrEmpty(text))
                throw new ArgumentException("Text required!","text");
            //var decodedKey = Convert.FromBase64String(key);
            var decodedKey = Encoding.UTF8.GetBytes(key);
            var plainText = Encoding.UTF8.GetBytes(text);
            var cipherText = EncryptWithKey(plainText,decodedKey,nonSecretPayload);
            return Convert.ToBase64String(cipherText);
        }

        //encrypt with byte array
        private byte[] EncryptWithKey(byte[] text,byte[] key,byte[] nonSecretPayload = null)
        {
            if (key == null || key.Length != KEY_BIT_SIZE / 8)
                throw new ArgumentException(String.Format("Key needs to be {0} bit!",KEY_BIT_SIZE),"key");

            nonSecretPayload = nonSecretPayload ?? new byte[] { };
            var nonce = new byte[NONCE_BIT_SIZE / 8];
            random.NextBytes(nonce,nonce.Length);
            var cipher = new GcmBlockCipher(new AesEngine());
            var parameters = new AeadParameters(new KeyParameter(key),MAC_BIT_SIZE,nonce,nonSecretPayload);
            cipher.Init(true,parameters);
            var cipherText = new byte[cipher.GetoutputSize(text.Length)];
            var len = cipher.ProcessBytes(text,text.Length,cipherText,0);
            cipher.DoFinal(cipherText,len);
            using (var combinedStream = new MemoryStream())
            {
                using (var binaryWriter = new BinaryWriter(combinedStream))
                {
                    binaryWriter.Write(nonSecretPayload);
                    binaryWriter.Write(nonce);
                    binaryWriter.Write(cipherText);
                }
                return combinedStream.ToArray();
            }
        }
    }
}

输出:总是在变化

示例 1 4BnestJ12YZIQsaFhOcufy1rgXW2/H5kBmPyBSVdf2qP

示例 2 z4xNJgr6YLg+lsCA2jUn0HKorN8UXrVm0QtKl10w/Yba

示例 3 0IxfAp2vIOmj3fvsJ25VVINHpnaxtZ5KNl89Qk7MNFcn

我想要输出 .net 相同的 java。我对加密和 Java 的了解都不够,不知道下一步该去哪里。任何指导将不胜感激

更新

我尝试遵循建议,但没有奏效。

using System;
using System.Text;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;

namespace api.Class
{
    public class AESGCM
    {
        private const int KEY_BIT_SIZE = 256;
        private const int MAC_BIT_SIZE = 128;

        //encrypt with strings
        public string Encrypt(string text,string key)
        {
            if (string.IsNullOrEmpty(text))
                throw new ArgumentException("Text required!","text");

            var decodedKey = Encoding.UTF8.GetBytes(key);
            var plainText = Encoding.UTF8.GetBytes(text);
            var cipherText = EncryptWithKey(plainText,decodedKey);
            return Convert.ToBase64String(cipherText);
        }

        //encrypt with byte array
        private byte[] EncryptWithKey(byte[] text,byte[] key)
        {
            if (key == null || key.Length != KEY_BIT_SIZE / 8)
                throw new ArgumentException(String.Format("Key needs to be {0} bit!","key");

            var nonce = new byte[12];
            var cipher = new GcmBlockCipher(new AesEngine());
            var parameters = new AeadParameters(new KeyParameter(key),nonce);
            cipher.Init(true,len);

            return cipherText;
        }
    }
}

输出:修复 7szCRlNpTMM+93eTi332Gdw=

最终代码

using System;
using System.Security.Cryptography;
using System.Text;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;

namespace api.Class
{
    public class AESGCM
    {
        private const int KEY_BIT_SIZE = 256;
        private const int MAC_BIT_SIZE = 128;

        //encrypt with strings
        public string Encrypt(string text,"text");

            var decodedKey = sha256_hash(key);
            var plainText = Encoding.UTF8.GetBytes(text);
            var cipherText = EncryptWithKey(plainText,len);

            return cipherText;
        }

        private byte[] sha256_hash(string value)
        {
            Byte[] result;

            using (var hash = SHA256.Create())
            {
                Encoding enc = Encoding.UTF8;
                result = hash.ComputeHash(enc.GetBytes(value));
            }

            return result;
        }
    }
}

输出:与java相同

非常感谢@user9014097

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。