From 6660e0a76673b4120b102be375dffe4ecde67dca Mon Sep 17 00:00:00 2001 From: virtual <1185513330@qq.com> Date: Tue, 17 Mar 2020 14:04:53 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E5=88=B0=20netstandard2.1=20?= =?UTF-8?q?=E7=89=88=E6=9C=AC=20Signed-off-by:=20virtual=20<1185513330@qq.?= =?UTF-8?q?com>?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- azure-pipelines.yml | 4 +- build.config | 2 +- build/version.props | 10 +- .../DotCommon.ConsoleTest.csproj | 2 +- samples/DotCommon.ConsoleTest/Program.cs | 4 +- .../DotCommon.AutoMapper.csproj | 6 +- .../DotCommon.Caching.csproj | 6 +- .../DotCommon.ImageUtility.csproj | 6 +- .../DotCommon.Json4Net.csproj | 6 +- .../DotCommon.Log4Net.csproj | 6 +- .../DotCommon.ProtoBuf.csproj | 2 +- src/DotCommon/DotCommon.csproj | 6 +- .../Encrypt/Netstandard2RSAHelper.cs | 800 ++++++++++++++++++ src/DotCommon/Encrypt/RSAHelper.cs | 655 +------------- .../Encrypt/Netstandard2RSAHelperTest.cs | 131 +++ test/DotCommon.Test/Encrypt/RSAHelperTest.cs | 28 +- 16 files changed, 1001 insertions(+), 673 deletions(-) create mode 100644 src/DotCommon/Encrypt/Netstandard2RSAHelper.cs create mode 100644 test/DotCommon.Test/Encrypt/Netstandard2RSAHelperTest.cs diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 8bfb186..83ef49b 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -18,7 +18,7 @@ jobs: steps: - task: DotNetCoreInstaller@0 inputs: - version: '3.1.102' + version: '3.1.200' - powershell: .\build.ps1 displayName: 'Run build.ps1' @@ -28,7 +28,7 @@ jobs: steps: - task: DotNetCoreInstaller@0 inputs: - version: '3.1.102' + version: '3.1.200' - script: | chmod +x ./build.sh displayName: 'Chmod build.sh' diff --git a/build.config b/build.config index 3f58658..7ae6200 100644 --- a/build.config +++ b/build.config @@ -1,3 +1,3 @@ #!/usr/bin/env bash CAKE_VERSION=0.36.0 -DOTNET_VERSION=3.1.102 \ No newline at end of file +DOTNET_VERSION=3.1.200 \ No newline at end of file diff --git a/build/version.props b/build/version.props index f11babc..de13ee9 100644 --- a/build/version.props +++ b/build/version.props @@ -1,10 +1,10 @@ - 3 - 1 - 6 - + 4 + 0 + 0 + 0 $(VersionMajor).$(VersionMinor).$(VersionPatch) - + Pre \ No newline at end of file diff --git a/samples/DotCommon.ConsoleTest/DotCommon.ConsoleTest.csproj b/samples/DotCommon.ConsoleTest/DotCommon.ConsoleTest.csproj index e606e96..a9d0f1c 100644 --- a/samples/DotCommon.ConsoleTest/DotCommon.ConsoleTest.csproj +++ b/samples/DotCommon.ConsoleTest/DotCommon.ConsoleTest.csproj @@ -12,7 +12,7 @@ - + diff --git a/samples/DotCommon.ConsoleTest/Program.cs b/samples/DotCommon.ConsoleTest/Program.cs index 59e1b47..db89188 100644 --- a/samples/DotCommon.ConsoleTest/Program.cs +++ b/samples/DotCommon.ConsoleTest/Program.cs @@ -94,8 +94,8 @@ static void Main(string[] args) //var p1 = RsaUtil.ReadPublicKeyInfo(publicKey1); - var privateKey2 = RSAHelper.ExportPrivateKeyPKCS1(privateParam); - var publicKey2 = RSAHelper.ExportPublicKey(publicParam); + var privateKey2 = Netstandard2RSAHelper.ExportPrivateKeyPKCS1(privateParam); + var publicKey2 = Netstandard2RSAHelper.ExportPublicKey(publicParam); Console.WriteLine("私钥:{0}", privateKey1); Console.WriteLine("私钥2:{0}", privateKey2); diff --git a/src/DotCommon.AutoMapper/DotCommon.AutoMapper.csproj b/src/DotCommon.AutoMapper/DotCommon.AutoMapper.csproj index 8207e9e..a4a089a 100644 --- a/src/DotCommon.AutoMapper/DotCommon.AutoMapper.csproj +++ b/src/DotCommon.AutoMapper/DotCommon.AutoMapper.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.1 DotCommon.AutoMapper DotCommon.AutoMapper DotCommon @@ -11,11 +11,11 @@ true - bin\Debug\netstandard2.0\DotCommon.AutoMapper.xml + bin\Debug\netstandard2.1\DotCommon.AutoMapper.xml - bin\Release\netstandard2.0\DotCommon.AutoMapper.xml + bin\Release\netstandard2.1\DotCommon.AutoMapper.xml true diff --git a/src/DotCommon.Caching/DotCommon.Caching.csproj b/src/DotCommon.Caching/DotCommon.Caching.csproj index eb1b513..788643e 100644 --- a/src/DotCommon.Caching/DotCommon.Caching.csproj +++ b/src/DotCommon.Caching/DotCommon.Caching.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.1 DotCommon.Caching DotCommon.Caching DotCommon @@ -11,11 +11,11 @@ true - bin\Debug\netstandard2.0\DotCommon.Caching.xml + bin\Debug\netstandard2.1\DotCommon.Caching.xml - bin\Release\netstandard2.0\DotCommon.Caching.xml + bin\Release\netstandard2.1\DotCommon.Caching.xml true diff --git a/src/DotCommon.ImageUtility/DotCommon.ImageUtility.csproj b/src/DotCommon.ImageUtility/DotCommon.ImageUtility.csproj index aa49c70..8c6bd86 100644 --- a/src/DotCommon.ImageUtility/DotCommon.ImageUtility.csproj +++ b/src/DotCommon.ImageUtility/DotCommon.ImageUtility.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.1 DotCommon.ImageUtility DotCommon.ImageUtility DotCommon @@ -11,11 +11,11 @@ true - bin\Debug\netstandard2.0\DotCommon.ImageUtility.xml + bin\Debug\netstandard2.1\DotCommon.ImageUtility.xml - bin\Release\netstandard2.0\DotCommon.ImageUtility.xml + bin\Release\netstandard2.1\DotCommon.ImageUtility.xml true diff --git a/src/DotCommon.Json4Net/DotCommon.Json4Net.csproj b/src/DotCommon.Json4Net/DotCommon.Json4Net.csproj index ce67de8..cd4dc01 100644 --- a/src/DotCommon.Json4Net/DotCommon.Json4Net.csproj +++ b/src/DotCommon.Json4Net/DotCommon.Json4Net.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.1 DotCommon.Json4Net DotCommon.Json4Net DotCommon @@ -11,11 +11,11 @@ true - bin\Debug\netstandard2.0\DotCommon.Json4Net.xml + bin\Debug\netstandard2.1\DotCommon.Json4Net.xml - bin\Release\netstandard2.0\DotCommon.Json4Net.xml + bin\Release\netstandard2.1\DotCommon.Json4Net.xml true diff --git a/src/DotCommon.Log4Net/DotCommon.Log4Net.csproj b/src/DotCommon.Log4Net/DotCommon.Log4Net.csproj index 6b37b77..518e87f 100644 --- a/src/DotCommon.Log4Net/DotCommon.Log4Net.csproj +++ b/src/DotCommon.Log4Net/DotCommon.Log4Net.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.1 DotCommon.Log4Net DotCommon.Log4Net DotCommon @@ -11,11 +11,11 @@ true - bin\Debug\netstandard2.0\DotCommon.Log4Net.xml + bin\Debug\netstandard2.1\DotCommon.Log4Net.xml - bin\Release\netstandard2.0\DotCommon.Log4Net.xml + bin\Release\netstandard2.1\DotCommon.Log4Net.xml true diff --git a/src/DotCommon.ProtoBuf/DotCommon.ProtoBuf.csproj b/src/DotCommon.ProtoBuf/DotCommon.ProtoBuf.csproj index 0aacbaa..fc2f5f4 100644 --- a/src/DotCommon.ProtoBuf/DotCommon.ProtoBuf.csproj +++ b/src/DotCommon.ProtoBuf/DotCommon.ProtoBuf.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.1 DotCommon.ProtoBuf DotCommon.ProtoBuf DotCommon diff --git a/src/DotCommon/DotCommon.csproj b/src/DotCommon/DotCommon.csproj index fc38c94..de7d045 100644 --- a/src/DotCommon/DotCommon.csproj +++ b/src/DotCommon/DotCommon.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.1 DotCommon DotCommon DotCommon @@ -11,11 +11,11 @@ true - bin\Debug\netstandard2.0\DotCommon.xml + bin\Debug\netstandard2.1\DotCommon.xml - bin\Release\netstandard2.0\DotCommon.xml + bin\Release\netstandard2.1\DotCommon.xml true diff --git a/src/DotCommon/Encrypt/Netstandard2RSAHelper.cs b/src/DotCommon/Encrypt/Netstandard2RSAHelper.cs new file mode 100644 index 0000000..dc3c231 --- /dev/null +++ b/src/DotCommon/Encrypt/Netstandard2RSAHelper.cs @@ -0,0 +1,800 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; + +namespace DotCommon.Encrypt +{ + /// RSA密码,密钥相关操作 + /// + public static class Netstandard2RSAHelper + { + /// 固定内容 encoded OID sequence for PKCS #1 rsaEncryption szOID_RSA_RSA ="1.2.840.113549.1.1.1" + /// + private static readonly byte[] SeqOID = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 }; + + /// 固定版本号 + /// + private static readonly byte[] Version = { 0x02, 0x01, 0x00 }; + + private static readonly Dictionary HashAlgorithmNameDict = new Dictionary() + { + {"MD5",HashAlgorithmName.MD5 }, + {"SHA1",HashAlgorithmName.SHA1 }, + {"SHA256",HashAlgorithmName.SHA256 }, + {"SHA384",HashAlgorithmName.SHA384 }, + {"SHA512",HashAlgorithmName.SHA512 }, + }; + + /// 生成RSA密钥对(Pem密钥格式) + /// + /// 格式,PKCS1或者PKCS8 + /// 512,1024,1536,2048 + /// 公钥,私钥 + public static RSAKeyPair GenerateKeyPair(RSAKeyFormat format = RSAKeyFormat.PKCS1, int keySize = 1024) + { + using (var rsa = RSA.Create()) + { + rsa.KeySize = keySize; + + var publicParameters = rsa.ExportParameters(false); + var privateParameters = rsa.ExportParameters(true); + string publicKey = ExportPublicKey(publicParameters); + string privateKey = format == RSAKeyFormat.PKCS1 ? ExportPrivateKeyPKCS1(privateParameters) : ExportPrivateKeyPKCS8(privateParameters); + return new RSAKeyPair(publicKey, privateKey); + } + } + + /// 根据RSAParameters参数生成公钥 + /// + /// RSA参数 + /// + public static string ExportPublicKey(RSAParameters rsaParameters) + { + //Exponent + var exponentBytes = TLVFormat(0x02, rsaParameters.Exponent); + //Modulus + var modulusBytes = TLVFormat(0x02, rsaParameters.Modulus); + var contentBytes = new List(); + contentBytes.AddRange(modulusBytes); + contentBytes.AddRange(exponentBytes); + contentBytes = TLVFormat(0x30, contentBytes.ToArray()); + contentBytes.Insert(0, 0x00); + + //内容,Modulus+Exponent + var bodyBytes = TLVFormat(0x03, contentBytes.ToArray()); + bodyBytes.InsertRange(0, SeqOID); + + //密钥最终的二进制 + var keyBytes = TLVFormat(0x30, bodyBytes.ToArray()); + return Convert.ToBase64String(keyBytes.ToArray()); + } + + /// 根据RSAParameters参数生成PKCS1私钥 + /// + /// RSA参数 + /// + public static string ExportPrivateKeyPKCS1(RSAParameters rsaParameters) + { + //密钥中,除了头部长度以外的数据 + var bodyBytes = new List(); + //版本号 + bodyBytes.AddRange(Version); + //Modulus + bodyBytes.AddRange(TLVFormat(0x02, rsaParameters.Modulus)); + //Exponent + bodyBytes.AddRange(TLVFormat(0x02, rsaParameters.Exponent)); + //D + bodyBytes.AddRange(TLVFormat(0x02, rsaParameters.D)); + //P + bodyBytes.AddRange(TLVFormat(0x02, rsaParameters.P)); + //Q + bodyBytes.AddRange(TLVFormat(0x02, rsaParameters.Q)); + //DP + bodyBytes.AddRange(TLVFormat(0x02, rsaParameters.DP)); + //DQ + bodyBytes.AddRange(TLVFormat(0x02, rsaParameters.DQ)); + //InverseQ + bodyBytes.AddRange(TLVFormat(0x02, rsaParameters.InverseQ)); + //密钥二进制 + var keyBytes = TLVFormat(0x30, bodyBytes.ToArray()); + return Convert.ToBase64String(keyBytes.ToArray()); + } + + /// 根据RSAParameters参数生成PKCS8私钥 + /// + public static string ExportPrivateKeyPKCS8(RSAParameters rsaParameters) + { + //第二个Verison之后的数据 + var contentBytes = new List(); + //版本号 + contentBytes.AddRange(Version); + + //Modulus + contentBytes.AddRange(TLVFormat(0x02, rsaParameters.Modulus)); + //Exponent + contentBytes.AddRange(TLVFormat(0x02, rsaParameters.Exponent)); + //D + contentBytes.AddRange(TLVFormat(0x02, rsaParameters.D)); + //P + contentBytes.AddRange(TLVFormat(0x02, rsaParameters.P)); + //Q + contentBytes.AddRange(TLVFormat(0x02, rsaParameters.Q)); + //DP + contentBytes.AddRange(TLVFormat(0x02, rsaParameters.DP)); + //DQ + contentBytes.AddRange(TLVFormat(0x02, rsaParameters.DQ)); + //InverseQ + contentBytes.AddRange(TLVFormat(0x02, rsaParameters.InverseQ)); + + //不包含第一个Version的tlv + var bodyTlvBytes = TLVFormat(0x30, contentBytes.ToArray()); + //SeqOid之后的tlv + var bodyBytes = TLVFormat(0x04, bodyTlvBytes.ToArray()); + bodyBytes.InsertRange(0, SeqOID); + bodyBytes.InsertRange(0, Version); + + //密钥二进制 + var keyBytes = TLVFormat(0x30, bodyBytes.ToArray()); + return Convert.ToBase64String(keyBytes.ToArray()); + } + + /// 将PKCS8编码格式的私钥转换成PKCS1编码格式的私钥 + /// + /// PKCS8格式密钥 + /// + public static string PKCS8ToPKCS1(string pkcs8Key) + { + var rsaParams = ReadPrivateKeyInfo(pkcs8Key); + return ExportPrivateKeyPKCS1(rsaParams); + } + + /// 将PKCS1编码格式的私钥转换成PKCS8编码格式的私钥 + /// + /// PKCS1格式密钥 + /// + public static string PKCS1ToPKCS8(string pkcs1Key) + { + var rsaParams = ReadPrivateKeyInfo(pkcs1Key); + return ExportPrivateKeyPKCS8(rsaParams); + } + + + + /// 从公钥中读取RSA参数 + /// + public static RSAParameters ReadPublicKeyInfo(string publicKey) + { + var rsaKeyInfo = new RSAParameters(); + //公钥二进制数据 + var keyBytes = Convert.FromBase64String(publicKey); + var keySpan = new Span(keyBytes); + if (keySpan[0] != 0x30) + { + throw new ArgumentException("RSA公钥头部标志位不正确,应该为0x30."); + } + var bodySpan = ReadContent(ReadTLV(keySpan)); + if (!SeqOID.SequenceEqual(bodySpan.Slice(0, 15).ToArray())) + { + throw new ArgumentException("RSA公钥OID sequence不正确."); + } + //内容 + var contentSpan = bodySpan.Slice(15); + if (contentSpan[0] != 0x03) + { + throw new ArgumentException("RSA公钥内容志位不正确,应该为0x03."); + } + //固定0x00 + var fixedSpan = ReadTLV(contentSpan); + if (fixedSpan[0] != 0x00) + { + throw new ArgumentException("RSA公钥固定内容不正确,应为0x00"); + } + //内容 + var keyContentSpan = ReadTLV(fixedSpan.Slice(1)); + if (keyContentSpan[0] != 0x02) + { + throw new ArgumentException("RSA公钥Modulus标志不正确,应为0x02."); + } + + var tlvs = SplitTLVs(keyContentSpan); + //Modulus + rsaKeyInfo.Modulus = ReadContent(tlvs[0]).ToArray(); + //Exponent + rsaKeyInfo.Exponent = ReadContent(tlvs[1]).ToArray(); + return rsaKeyInfo; + } + + /// 从私钥中读取RSA参数 + /// + public static RSAParameters ReadPrivateKeyInfo(string privateKey) + { + var rsaKeyInfo = new RSAParameters(); + var keyBytes = Convert.FromBase64String(privateKey); + var keySpan = new Span(keyBytes); + if (keySpan[0] != 0x30) + { + throw new ArgumentException("RSA私钥头部标志位不正确,应该为0x30."); + } + //Body + var bodySpan = ReadTLV(keySpan); + if (!Version.SequenceEqual(bodySpan.Slice(0, 3).ToArray())) + { + throw new ArgumentException("RSA私钥第一个固定版本不正确."); + } + //内容 + var contentSpan = bodySpan.Slice(3); + + if (contentSpan[0] == 0x30) + { + //PKCS8 + if (!SeqOID.SequenceEqual(contentSpan.Slice(0, 15).ToArray())) + { + throw new ArgumentException("RSA私钥为PKCS8格式,OID sequence不正确"); + } + //去除了OID之后的数据 + var itemSpan1 = contentSpan.Slice(15); + var itemSpan2 = ReadTLV(itemSpan1); + var secondVersionSpan = ReadTLV(itemSpan2); + //第二个版本读取 + if (!Version.SequenceEqual(secondVersionSpan.Slice(0, 3).ToArray())) + { + throw new ArgumentException("RSA私钥为PKCS8格式,第二个固定版本不正确."); + } + //两种格式私钥的内容 + contentSpan = secondVersionSpan.Slice(3); + } + //多个并列tlv + var tlvs = SplitTLVs(contentSpan); + //Modulus + rsaKeyInfo.Modulus = ReadContent(tlvs[0]).ToArray(); + //Exponent + rsaKeyInfo.Exponent = ReadContent(tlvs[1]).ToArray(); + //D + rsaKeyInfo.D = ReadContent(tlvs[2]).ToArray(); + //P + rsaKeyInfo.P = ReadContent(tlvs[3]).ToArray(); + //Q + rsaKeyInfo.Q = ReadContent(tlvs[4]).ToArray(); + //DP + rsaKeyInfo.DP = ReadContent(tlvs[5]).ToArray(); + //DQ + rsaKeyInfo.DQ = ReadContent(tlvs[6]).ToArray(); + //InverseQ + rsaKeyInfo.InverseQ = ReadContent(tlvs[7]).ToArray(); + return rsaKeyInfo; + } + + /// 获取RSA私钥的格式 + /// + public static RSAKeyFormat GetKeyFormat(string privateKey) + { + var keyFormat = RSAKeyFormat.PKCS1; + var keyBytes = Convert.FromBase64String(privateKey); + var keySpan = new Span(keyBytes); + if (keySpan[0] != 0x30) + { + return RSAKeyFormat.Unknow; + } + //Body + var bodySpan = ReadTLV(keySpan); + if (!Version.SequenceEqual(bodySpan.Slice(0, 3).ToArray())) + { + return RSAKeyFormat.Unknow; + } + //内容 + var contentSpan = bodySpan.Slice(3); + if (contentSpan[0] == 0x30) + { + keyFormat = RSAKeyFormat.PKCS8; + } + return keyFormat; + } + + + + #region RSA加密解密,签名解签 + + /// 加密 + /// + /// 原数据 + /// 公钥 + /// 算法 + /// + public static byte[] Encrypt(byte[] data, string publicKey, RSAEncryptionPadding encryptionPadding = null) + { + using (var rsa = CreateRsaFromPublicKey(publicKey)) + { + encryptionPadding ??= RSAEncryptionPadding.Pkcs1; + var encryptedData = rsa.Encrypt(data, encryptionPadding); + return encryptedData; + } + } + + /// 加密 + /// + /// 原数据 + /// 公钥 + /// 算法 + /// 编码 + /// + public static string EncryptAsBase64(string data, string publicKey, RSAEncryptionPadding encryptionPadding = null, string encode = "utf-8") + { + var encryptedData = Encrypt(Encoding.GetEncoding(encode).GetBytes(data), publicKey, encryptionPadding); + return Convert.ToBase64String(encryptedData); + } + + + /// 解密 + /// + /// 待解密数据 + /// + /// 算法 + /// + public static byte[] Decrypt(byte[] data, string privateKey, RSAEncryptionPadding encryptionPadding = null) + { + using (var rsa = CreateRsaFromPrivateKey(privateKey)) + { + encryptionPadding ??= RSAEncryptionPadding.Pkcs1; + var decryptedData = rsa.Decrypt(data, encryptionPadding); + return decryptedData; + } + } + + + /// 解密 + /// + /// 原数据 + /// 私钥 + /// 算法 + /// 编码 + /// + public static string DecryptFromBase64(string data, string privateKey, RSAEncryptionPadding encryptionPadding = null, string encode = "utf-8") + { + var decryptedData = Decrypt(Convert.FromBase64String(data), privateKey, encryptionPadding); + return Encoding.GetEncoding(encode).GetString(decryptedData); + } + + + /// 数据签名 + /// + /// 待签名数据 + /// 私钥 + /// 签名类型 + /// 哈希算法 + /// + + public static byte[] SignData(byte[] data, string privateKey, RSASignaturePadding signaturePadding = null, string hashAlgorithmName = "SHA256") + { + using (var rsa = CreateRsaFromPrivateKey(privateKey)) + { + signaturePadding ??= RSASignaturePadding.Pkcs1; + var signedData = rsa.SignData(data, HashAlgorithmNameDict[hashAlgorithmName], signaturePadding); + return signedData; + } + } + /// 数据签名 + /// + /// 待签名数据 + /// 私钥 + /// 签名类型 + /// 哈希算法 + /// 编码 + /// + public static string SignDataAsBase64(string data, string privateKey, RSASignaturePadding signaturePadding = null, string hashAlgorithmName = "SHA256", string encode = "utf-8") + { + var signedData = SignData(Encoding.GetEncoding(encode).GetBytes(data), privateKey, signaturePadding, hashAlgorithmName); + return Convert.ToBase64String(signedData); + } + + /// 签名校验 + /// + /// 原数据 + /// 签名后数据 + /// 公寓奥 + /// 签名算法 + /// 哈希算法 + /// + public static bool VerifyData(byte[] data, byte[] signature, string publicKey, RSASignaturePadding signaturePadding = null, string hashAlgorithmName = "SHA256") + { + using (var rsa = CreateRsaFromPublicKey(publicKey)) + { + signaturePadding ??= RSASignaturePadding.Pkcs1; + return rsa.VerifyData(data, signature, HashAlgorithmNameDict[hashAlgorithmName], signaturePadding); + } + } + + /// 签名校验 + /// + /// 源数据 + /// 签名后数据Base64编码 + /// 公寓奥 + /// 签名算法 + /// 哈希算法 + /// 编码 + /// + public static bool VerifyBase64Data(string data, string base64Signature, string publicKey, RSASignaturePadding signaturePadding = null, string hashAlgorithmName = "SHA256", string encode = "utf-8") + { + var dataBytes = Encoding.GetEncoding(encode).GetBytes(data); + var signature = Convert.FromBase64String(base64Signature); + return VerifyData(dataBytes, signature, publicKey, signaturePadding, hashAlgorithmName); + } + + + + /// 根据RSA公钥生成RSA对象 + /// + private static RSA CreateRsaFromPublicKey(string publicKey) + { + var rsaParams = ReadPublicKeyInfo(publicKey); + var rsa = RSA.Create(); + rsa.ImportParameters(rsaParams); + return rsa; + + #region 原方法 + ////1.2.840.113549.1.1.1 + //byte[] seqOid = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 }; + //var x509Key = Convert.FromBase64String(publicKey); + //using (var mem = new MemoryStream(x509Key)) + //{ + // using (var binr = new BinaryReader(mem)) + // { + // byte bt = 0; + // ushort twobytes = 0; + + // twobytes = binr.ReadUInt16(); + // if (twobytes == 0x8130) + // { + // binr.ReadByte(); + // } + // else if (twobytes == 0x8230) + // { + // binr.ReadInt16(); + // } + // else + // { + // return null; + // } + // var seq = binr.ReadBytes(15); + // if (!CompareByteArray(seq, seqOid)) + // { + // return null; + // } + + // twobytes = binr.ReadUInt16(); + // if (twobytes == 0x8103) + // { + // binr.ReadByte(); + // } + // else if (twobytes == 0x8203) + // { + // binr.ReadInt16(); + // } + // else + // { + // return null; + // } + // bt = binr.ReadByte(); + // if (bt != 0x00) + // { + // return null; + // } + // twobytes = binr.ReadUInt16(); + // if (twobytes == 0x8130) + // { + // binr.ReadByte(); + // } + // else if (twobytes == 0x8230) + // { + // binr.ReadInt16(); + // } + // else + // { + // return null; + // } + // twobytes = binr.ReadUInt16(); + // byte lowbyte = 0x00; + // byte highbyte = 0x00; + + // if (twobytes == 0x8102) + // { + // lowbyte = binr.ReadByte(); + // } + // else if (twobytes == 0x8202) + // { + // highbyte = binr.ReadByte(); + // lowbyte = binr.ReadByte(); + // } + // else + // { + // return null; + // } + // byte[] modint = { lowbyte, highbyte, 0x00, 0x00 }; + // int modsize = BitConverter.ToInt32(modint, 0); + + // int firstbyte = binr.PeekChar(); + // if (firstbyte == 0x00) + // { + // binr.ReadByte(); + // modsize -= 1; + // } + // byte[] modulus = binr.ReadBytes(modsize); + // if (binr.ReadByte() != 0x02) + // { + // return null; + // } + // int expbytes = (int)binr.ReadByte(); + // byte[] exponent = binr.ReadBytes(expbytes); + // var rsa = RSA.Create(); + // var rsaKeyInfo = new RSAParameters + // { + // Modulus = modulus, + // Exponent = exponent + // }; + // rsa.ImportParameters(rsaKeyInfo); + // return rsa; + // } + + //} + #endregion + } + + /// 根据私钥生成RSA对象 + /// + private static RSA CreateRsaFromPrivateKey(string privateKey) + { + RSAParameters rsaParams = ReadPrivateKeyInfo(privateKey); + var rsa = RSA.Create(); + rsa.ImportParameters(rsaParams); + return rsa; + + #region 原方法 + //var privateKeyBits = Convert.FromBase64String(privateKey); + //var rsa = RSA.Create(); + //var rsaParams = new RSAParameters(); + + //using (var binr = new BinaryReader(new MemoryStream(privateKeyBits))) + //{ + // byte bt = 0; + // ushort twobytes = 0; + // twobytes = binr.ReadUInt16(); + // if (twobytes == 0x8130) + // { + // binr.ReadByte(); + // } + // else if (twobytes == 0x8230) + // { + // binr.ReadInt16(); + // } + // else + // { + // throw new Exception("Unexpected value read binr.ReadUInt16()"); + // } + // twobytes = binr.ReadUInt16(); + // if (twobytes != 0x0102) + // { + // throw new Exception("Unexpected version"); + // } + // bt = binr.ReadByte(); + // if (bt != 0x00) + // { + // throw new Exception("Unexpected value read binr.ReadByte()"); + // } + // rsaParams.Modulus = binr.ReadBytes(GetIntegerSize(binr)); + // rsaParams.Exponent = binr.ReadBytes(GetIntegerSize(binr)); + // rsaParams.D = binr.ReadBytes(GetIntegerSize(binr)); + // rsaParams.P = binr.ReadBytes(GetIntegerSize(binr)); + // rsaParams.Q = binr.ReadBytes(GetIntegerSize(binr)); + // rsaParams.DP = binr.ReadBytes(GetIntegerSize(binr)); + // rsaParams.DQ = binr.ReadBytes(GetIntegerSize(binr)); + // rsaParams.InverseQ = binr.ReadBytes(GetIntegerSize(binr)); + //} + //rsa.ImportParameters(rsaParams); + //return rsa; + #endregion + } + + #endregion + + /// TLV格式化(flag+长度数据占用位数+长度数值+数据) + /// + /// 标志 + /// + /// + private static List TLVFormat(byte flag, byte[] content) + { + var tlvBytes = new List + { + flag + }; + var contentLength = content.Length; + //判断是否需要添加0x00 + if (content[0] >= 0x80) + { + contentLength++; + } + //长度小于0x80(128,因为byte最大表示0-127),数据长度占用位没有了 + if (contentLength >= 0x80) + { + //小于256,0xFF=255 + if (contentLength <= 0xFF) + { + tlvBytes.Add(0x81); + tlvBytes.Add((byte)contentLength); + } + else + { + tlvBytes.Add(0x82); + var lengthBytes = BitConverter.GetBytes((ushort)contentLength).Reverse(); + tlvBytes.AddRange(lengthBytes); + } + } + else + { + //长度小于128,直接添加1位的长度 + tlvBytes.Add((byte)contentLength); + } + //判断是否需要添加0x00 + if (content[0] >= 0x80) + { + tlvBytes.Add(0x00); + } + //添加内容 + tlvBytes.AddRange(content); + return tlvBytes; + } + + /// 读取TLV结构中的数据 + /// + private static Span ReadTLV(Span tlvSpan) + { + //长度 + int length; + Span contentSpan; + //如果该值小于0x80,代表没有长度占用位 + if (tlvSpan[1] < 0x80) + { + length = tlvSpan[1]; + contentSpan = tlvSpan.Slice(2, length); + } + else if (tlvSpan[1] == 0x81) + { + length = tlvSpan[2]; + contentSpan = tlvSpan.Slice(3, length); + } + else if (tlvSpan[1] == 0x82) + { + var lengthSpan = tlvSpan.Slice(2, 2); + lengthSpan.Reverse(); + length = BitConverter.ToUInt16(lengthSpan.ToArray(), 0); + contentSpan = tlvSpan.Slice(4, length); + } + else + { + throw new ArgumentException("TLV长度占用位不正确,应为0x81或者0x82"); + } + return contentSpan; + } + + /// 分割多个TLV格式数据,返回数据列表 + /// + private static List SplitTLVs(Span tlvs) + { + var tlvList = new List(); + var tlvSpan = tlvs.Slice(0); + var readLength = 0; + while (readLength < tlvs.Length) + { + //长度 + int length; + //当前Item的长度 + int itemLength = 1; + Span contentSpan; + //如果该值小于0x80,代表没有长度占用位 + if (tlvSpan[1] < 0x80) + { + length = tlvSpan[1]; + contentSpan = tlvSpan.Slice(2, length); + itemLength += 1; + } + else if (tlvSpan[1] == 0x81) + { + length = tlvSpan[2]; + contentSpan = tlvSpan.Slice(3, length); + itemLength += 2; + } + else if (tlvSpan[1] == 0x82) + { + //长度占用2个字节 + var lengthSpan = tlvSpan.Slice(2, 2); + lengthSpan.Reverse(); + length = BitConverter.ToUInt16(lengthSpan.ToArray(), 0); + contentSpan = tlvSpan.Slice(4, length); + itemLength += 3; + } + else + { + throw new ArgumentException("TLV长度占用位不正确,应为0x81或者0x82"); + } + tlvList.Add(contentSpan.ToArray()); + itemLength += length; + tlvSpan = tlvSpan.Slice(itemLength); + readLength += itemLength; + } + return tlvList; + } + + /// 读取内容数据 + /// + private static Span ReadContent(Span contentSpan) + { + if (contentSpan[0] == 0x00) + { + if (contentSpan[1] < 0x80) + { + throw new ArgumentException("RSA读取内容数据首位小于0x80不需要补0x00"); + } + return contentSpan.Slice(1); + } + else + { + return contentSpan.Slice(0); + } + } + } + + /// RSA私钥编码格式 + /// + public enum RSAKeyFormat + { + /// PKCS1 + /// + PKCS1 = 1, + + /// PKCS8 + /// + PKCS8 = 2, + + /// 未知 + /// + Unknow = 4 + } + + /// RSA密钥对 + /// + public class RSAKeyPair : IEquatable + { + /// 公钥 + /// + public string PublicKey { get; set; } + + /// 私钥 + /// + public string PrivateKey { get; set; } + + /// Ctor + /// + public RSAKeyPair() + { + + } + + /// Ctor + /// + public RSAKeyPair(string publicKey, string privateKey) + { + PublicKey = publicKey; + PrivateKey = privateKey; + } + + /// 是否相同 + /// + public bool Equals(RSAKeyPair other) + { + return other.PrivateKey == PrivateKey && other.PublicKey == PublicKey; + } + } + + +} diff --git a/src/DotCommon/Encrypt/RSAHelper.cs b/src/DotCommon/Encrypt/RSAHelper.cs index 7dcbfaf..870ef01 100644 --- a/src/DotCommon/Encrypt/RSAHelper.cs +++ b/src/DotCommon/Encrypt/RSAHelper.cs @@ -1,22 +1,14 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Security.Cryptography; using System.Text; namespace DotCommon.Encrypt { - /// RSA密码,密钥相关操作 + /// 基于Netstandard2.1平台下的RSA操作 /// - public static class RSAHelper + public class RSAHelper { - /// 固定内容 encoded OID sequence for PKCS #1 rsaEncryption szOID_RSA_RSA ="1.2.840.113549.1.1.1" - /// - private static readonly byte[] SeqOID = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 }; - - /// 固定版本号 - /// - private static readonly byte[] Version = { 0x02, 0x01, 0x00 }; private static readonly Dictionary HashAlgorithmNameDict = new Dictionary() { @@ -38,107 +30,14 @@ public static RSAKeyPair GenerateKeyPair(RSAKeyFormat format = RSAKeyFormat.PKCS { rsa.KeySize = keySize; - var publicParameters = rsa.ExportParameters(false); - var privateParameters = rsa.ExportParameters(true); - string publicKey = ExportPublicKey(publicParameters); - string privateKey = format == RSAKeyFormat.PKCS1 ? ExportPrivateKeyPKCS1(privateParameters) : ExportPrivateKeyPKCS8(privateParameters); + var privateKeyBuffer = format == RSAKeyFormat.PKCS1 ? rsa.ExportRSAPrivateKey() : rsa.ExportPkcs8PrivateKey(); + var privateKey = Convert.ToBase64String(privateKeyBuffer); + var publicKeyBuffer = rsa.ExportRSAPublicKey(); + var publicKey = Convert.ToBase64String(publicKeyBuffer); return new RSAKeyPair(publicKey, privateKey); } } - /// 根据RSAParameters参数生成公钥 - /// - /// RSA参数 - /// - public static string ExportPublicKey(RSAParameters rsaParameters) - { - //Exponent - var exponentBytes = TLVFormat(0x02, rsaParameters.Exponent); - //Modulus - var modulusBytes = TLVFormat(0x02, rsaParameters.Modulus); - var contentBytes = new List(); - contentBytes.AddRange(modulusBytes); - contentBytes.AddRange(exponentBytes); - contentBytes = TLVFormat(0x30, contentBytes.ToArray()); - contentBytes.Insert(0, 0x00); - - //内容,Modulus+Exponent - var bodyBytes = TLVFormat(0x03, contentBytes.ToArray()); - bodyBytes.InsertRange(0, SeqOID); - - //密钥最终的二进制 - var keyBytes = TLVFormat(0x30, bodyBytes.ToArray()); - return Convert.ToBase64String(keyBytes.ToArray()); - } - - /// 根据RSAParameters参数生成PKCS1私钥 - /// - /// RSA参数 - /// - public static string ExportPrivateKeyPKCS1(RSAParameters rsaParameters) - { - //密钥中,除了头部长度以外的数据 - var bodyBytes = new List(); - //版本号 - bodyBytes.AddRange(Version); - //Modulus - bodyBytes.AddRange(TLVFormat(0x02, rsaParameters.Modulus)); - //Exponent - bodyBytes.AddRange(TLVFormat(0x02, rsaParameters.Exponent)); - //D - bodyBytes.AddRange(TLVFormat(0x02, rsaParameters.D)); - //P - bodyBytes.AddRange(TLVFormat(0x02, rsaParameters.P)); - //Q - bodyBytes.AddRange(TLVFormat(0x02, rsaParameters.Q)); - //DP - bodyBytes.AddRange(TLVFormat(0x02, rsaParameters.DP)); - //DQ - bodyBytes.AddRange(TLVFormat(0x02, rsaParameters.DQ)); - //InverseQ - bodyBytes.AddRange(TLVFormat(0x02, rsaParameters.InverseQ)); - //密钥二进制 - var keyBytes = TLVFormat(0x30, bodyBytes.ToArray()); - return Convert.ToBase64String(keyBytes.ToArray()); - } - - /// 根据RSAParameters参数生成PKCS8私钥 - /// - public static string ExportPrivateKeyPKCS8(RSAParameters rsaParameters) - { - //第二个Verison之后的数据 - var contentBytes = new List(); - //版本号 - contentBytes.AddRange(Version); - - //Modulus - contentBytes.AddRange(TLVFormat(0x02, rsaParameters.Modulus)); - //Exponent - contentBytes.AddRange(TLVFormat(0x02, rsaParameters.Exponent)); - //D - contentBytes.AddRange(TLVFormat(0x02, rsaParameters.D)); - //P - contentBytes.AddRange(TLVFormat(0x02, rsaParameters.P)); - //Q - contentBytes.AddRange(TLVFormat(0x02, rsaParameters.Q)); - //DP - contentBytes.AddRange(TLVFormat(0x02, rsaParameters.DP)); - //DQ - contentBytes.AddRange(TLVFormat(0x02, rsaParameters.DQ)); - //InverseQ - contentBytes.AddRange(TLVFormat(0x02, rsaParameters.InverseQ)); - - //不包含第一个Version的tlv - var bodyTlvBytes = TLVFormat(0x30, contentBytes.ToArray()); - //SeqOid之后的tlv - var bodyBytes = TLVFormat(0x04, bodyTlvBytes.ToArray()); - bodyBytes.InsertRange(0, SeqOID); - bodyBytes.InsertRange(0, Version); - - //密钥二进制 - var keyBytes = TLVFormat(0x30, bodyBytes.ToArray()); - return Convert.ToBase64String(keyBytes.ToArray()); - } /// 将PKCS8编码格式的私钥转换成PKCS1编码格式的私钥 /// @@ -146,8 +45,13 @@ public static string ExportPrivateKeyPKCS8(RSAParameters rsaParameters) /// public static string PKCS8ToPKCS1(string pkcs8Key) { - var rsaParams = ReadPrivateKeyInfo(pkcs8Key); - return ExportPrivateKeyPKCS1(rsaParams); + using (var rsa = RSA.Create()) + { + var pkcs8KeyBuffer = Convert.FromBase64String(pkcs8Key); + rsa.ImportPkcs8PrivateKey(pkcs8KeyBuffer, out int bytesRead); + var pkcs1KeyBuffer = rsa.ExportRSAPrivateKey(); + return Convert.ToBase64String(pkcs1KeyBuffer); + } } /// 将PKCS1编码格式的私钥转换成PKCS8编码格式的私钥 @@ -156,144 +60,15 @@ public static string PKCS8ToPKCS1(string pkcs8Key) /// public static string PKCS1ToPKCS8(string pkcs1Key) { - var rsaParams = ReadPrivateKeyInfo(pkcs1Key); - return ExportPrivateKeyPKCS8(rsaParams); - } - - - - /// 从公钥中读取RSA参数 - /// - public static RSAParameters ReadPublicKeyInfo(string publicKey) - { - var rsaKeyInfo = new RSAParameters(); - //公钥二进制数据 - var keyBytes = Convert.FromBase64String(publicKey); - var keySpan = new Span(keyBytes); - if (keySpan[0] != 0x30) - { - throw new ArgumentException("RSA公钥头部标志位不正确,应该为0x30."); - } - var bodySpan = ReadContent(ReadTLV(keySpan)); - if (!SeqOID.SequenceEqual(bodySpan.Slice(0, 15).ToArray())) - { - throw new ArgumentException("RSA公钥OID sequence不正确."); - } - //内容 - var contentSpan = bodySpan.Slice(15); - if (contentSpan[0] != 0x03) - { - throw new ArgumentException("RSA公钥内容志位不正确,应该为0x03."); - } - //固定0x00 - var fixedSpan = ReadTLV(contentSpan); - if (fixedSpan[0] != 0x00) - { - throw new ArgumentException("RSA公钥固定内容不正确,应为0x00"); - } - //内容 - var keyContentSpan = ReadTLV(fixedSpan.Slice(1)); - if (keyContentSpan[0] != 0x02) - { - throw new ArgumentException("RSA公钥Modulus标志不正确,应为0x02."); - } - - var tlvs = SplitTLVs(keyContentSpan); - //Modulus - rsaKeyInfo.Modulus = ReadContent(tlvs[0]).ToArray(); - //Exponent - rsaKeyInfo.Exponent = ReadContent(tlvs[1]).ToArray(); - return rsaKeyInfo; - } - - /// 从私钥中读取RSA参数 - /// - public static RSAParameters ReadPrivateKeyInfo(string privateKey) - { - var rsaKeyInfo = new RSAParameters(); - var keyBytes = Convert.FromBase64String(privateKey); - var keySpan = new Span(keyBytes); - if (keySpan[0] != 0x30) - { - throw new ArgumentException("RSA私钥头部标志位不正确,应该为0x30."); - } - //Body - var bodySpan = ReadTLV(keySpan); - if (!Version.SequenceEqual(bodySpan.Slice(0, 3).ToArray())) - { - throw new ArgumentException("RSA私钥第一个固定版本不正确."); - } - //内容 - var contentSpan = bodySpan.Slice(3); - - if (contentSpan[0] == 0x30) - { - //PKCS8 - if (!SeqOID.SequenceEqual(contentSpan.Slice(0, 15).ToArray())) - { - throw new ArgumentException("RSA私钥为PKCS8格式,OID sequence不正确"); - } - //去除了OID之后的数据 - var itemSpan1 = contentSpan.Slice(15); - var itemSpan2 = ReadTLV(itemSpan1); - var secondVersionSpan = ReadTLV(itemSpan2); - //第二个版本读取 - if (!Version.SequenceEqual(secondVersionSpan.Slice(0, 3).ToArray())) - { - throw new ArgumentException("RSA私钥为PKCS8格式,第二个固定版本不正确."); - } - //两种格式私钥的内容 - contentSpan = secondVersionSpan.Slice(3); - } - //多个并列tlv - var tlvs = SplitTLVs(contentSpan); - //Modulus - rsaKeyInfo.Modulus = ReadContent(tlvs[0]).ToArray(); - //Exponent - rsaKeyInfo.Exponent = ReadContent(tlvs[1]).ToArray(); - //D - rsaKeyInfo.D = ReadContent(tlvs[2]).ToArray(); - //P - rsaKeyInfo.P = ReadContent(tlvs[3]).ToArray(); - //Q - rsaKeyInfo.Q = ReadContent(tlvs[4]).ToArray(); - //DP - rsaKeyInfo.DP = ReadContent(tlvs[5]).ToArray(); - //DQ - rsaKeyInfo.DQ = ReadContent(tlvs[6]).ToArray(); - //InverseQ - rsaKeyInfo.InverseQ = ReadContent(tlvs[7]).ToArray(); - return rsaKeyInfo; - } - - /// 获取RSA私钥的格式 - /// - public static RSAKeyFormat GetKeyFormat(string privateKey) - { - var keyFormat = RSAKeyFormat.PKCS1; - var keyBytes = Convert.FromBase64String(privateKey); - var keySpan = new Span(keyBytes); - if (keySpan[0] != 0x30) - { - return RSAKeyFormat.Unknow; - } - //Body - var bodySpan = ReadTLV(keySpan); - if (!Version.SequenceEqual(bodySpan.Slice(0, 3).ToArray())) - { - return RSAKeyFormat.Unknow; - } - //内容 - var contentSpan = bodySpan.Slice(3); - if (contentSpan[0] == 0x30) + using (var rsa = RSA.Create()) { - keyFormat = RSAKeyFormat.PKCS8; + var pkcs1KeyBuffer = Convert.FromBase64String(pkcs1Key); + rsa.ImportRSAPrivateKey(pkcs1KeyBuffer, out int bytesRead); + var pkcs8KeyBuffer = rsa.ExportPkcs8PrivateKey(); + return Convert.ToBase64String(pkcs8KeyBuffer); } - return keyFormat; } - - #region RSA加密解密,签名解签 /// 加密 @@ -304,8 +79,11 @@ public static RSAKeyFormat GetKeyFormat(string privateKey) /// public static byte[] Encrypt(byte[] data, string publicKey, RSAEncryptionPadding encryptionPadding = null) { - using (var rsa = CreateRsaFromPublicKey(publicKey)) + using (var rsa = RSA.Create()) { + var publicKeyBuffer = Convert.FromBase64String(publicKey); + rsa.ImportRSAPublicKey(publicKeyBuffer, out int bytesRead); + encryptionPadding ??= RSAEncryptionPadding.Pkcs1; var encryptedData = rsa.Encrypt(data, encryptionPadding); return encryptedData; @@ -334,8 +112,11 @@ public static string EncryptAsBase64(string data, string publicKey, RSAEncryptio /// public static byte[] Decrypt(byte[] data, string privateKey, RSAEncryptionPadding encryptionPadding = null) { - using (var rsa = CreateRsaFromPrivateKey(privateKey)) + using (var rsa = RSA.Create()) { + var privateKeyBuffer = Convert.FromBase64String(privateKey); + rsa.ImportRSAPrivateKey(privateKeyBuffer, out int bytesRead); + encryptionPadding ??= RSAEncryptionPadding.Pkcs1; var decryptedData = rsa.Decrypt(data, encryptionPadding); return decryptedData; @@ -367,8 +148,11 @@ public static string DecryptFromBase64(string data, string privateKey, RSAEncryp public static byte[] SignData(byte[] data, string privateKey, RSASignaturePadding signaturePadding = null, string hashAlgorithmName = "SHA256") { - using (var rsa = CreateRsaFromPrivateKey(privateKey)) + using (var rsa = RSA.Create()) { + var privateKeyBuffer = Convert.FromBase64String(privateKey); + rsa.ImportRSAPrivateKey(privateKeyBuffer, out int bytesRead); + signaturePadding ??= RSASignaturePadding.Pkcs1; var signedData = rsa.SignData(data, HashAlgorithmNameDict[hashAlgorithmName], signaturePadding); return signedData; @@ -398,8 +182,11 @@ public static string SignDataAsBase64(string data, string privateKey, RSASignatu /// public static bool VerifyData(byte[] data, byte[] signature, string publicKey, RSASignaturePadding signaturePadding = null, string hashAlgorithmName = "SHA256") { - using (var rsa = CreateRsaFromPublicKey(publicKey)) + using (var rsa = RSA.Create()) { + var publicKeyBuffer = Convert.FromBase64String(publicKey); + rsa.ImportRSAPublicKey(publicKeyBuffer, out int bytesRead); + signaturePadding ??= RSASignaturePadding.Pkcs1; return rsa.VerifyData(data, signature, HashAlgorithmNameDict[hashAlgorithmName], signaturePadding); } @@ -420,381 +207,7 @@ public static bool VerifyBase64Data(string data, string base64Signature, string var signature = Convert.FromBase64String(base64Signature); return VerifyData(dataBytes, signature, publicKey, signaturePadding, hashAlgorithmName); } - - - - /// 根据RSA公钥生成RSA对象 - /// - private static RSA CreateRsaFromPublicKey(string publicKey) - { - var rsaParams = ReadPublicKeyInfo(publicKey); - var rsa = RSA.Create(); - rsa.ImportParameters(rsaParams); - return rsa; - - #region 原方法 - ////1.2.840.113549.1.1.1 - //byte[] seqOid = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 }; - //var x509Key = Convert.FromBase64String(publicKey); - //using (var mem = new MemoryStream(x509Key)) - //{ - // using (var binr = new BinaryReader(mem)) - // { - // byte bt = 0; - // ushort twobytes = 0; - - // twobytes = binr.ReadUInt16(); - // if (twobytes == 0x8130) - // { - // binr.ReadByte(); - // } - // else if (twobytes == 0x8230) - // { - // binr.ReadInt16(); - // } - // else - // { - // return null; - // } - // var seq = binr.ReadBytes(15); - // if (!CompareByteArray(seq, seqOid)) - // { - // return null; - // } - - // twobytes = binr.ReadUInt16(); - // if (twobytes == 0x8103) - // { - // binr.ReadByte(); - // } - // else if (twobytes == 0x8203) - // { - // binr.ReadInt16(); - // } - // else - // { - // return null; - // } - // bt = binr.ReadByte(); - // if (bt != 0x00) - // { - // return null; - // } - // twobytes = binr.ReadUInt16(); - // if (twobytes == 0x8130) - // { - // binr.ReadByte(); - // } - // else if (twobytes == 0x8230) - // { - // binr.ReadInt16(); - // } - // else - // { - // return null; - // } - // twobytes = binr.ReadUInt16(); - // byte lowbyte = 0x00; - // byte highbyte = 0x00; - - // if (twobytes == 0x8102) - // { - // lowbyte = binr.ReadByte(); - // } - // else if (twobytes == 0x8202) - // { - // highbyte = binr.ReadByte(); - // lowbyte = binr.ReadByte(); - // } - // else - // { - // return null; - // } - // byte[] modint = { lowbyte, highbyte, 0x00, 0x00 }; - // int modsize = BitConverter.ToInt32(modint, 0); - - // int firstbyte = binr.PeekChar(); - // if (firstbyte == 0x00) - // { - // binr.ReadByte(); - // modsize -= 1; - // } - // byte[] modulus = binr.ReadBytes(modsize); - // if (binr.ReadByte() != 0x02) - // { - // return null; - // } - // int expbytes = (int)binr.ReadByte(); - // byte[] exponent = binr.ReadBytes(expbytes); - // var rsa = RSA.Create(); - // var rsaKeyInfo = new RSAParameters - // { - // Modulus = modulus, - // Exponent = exponent - // }; - // rsa.ImportParameters(rsaKeyInfo); - // return rsa; - // } - - //} - #endregion - } - - /// 根据私钥生成RSA对象 - /// - private static RSA CreateRsaFromPrivateKey(string privateKey) - { - RSAParameters rsaParams = ReadPrivateKeyInfo(privateKey); - var rsa = RSA.Create(); - rsa.ImportParameters(rsaParams); - return rsa; - - #region 原方法 - //var privateKeyBits = Convert.FromBase64String(privateKey); - //var rsa = RSA.Create(); - //var rsaParams = new RSAParameters(); - - //using (var binr = new BinaryReader(new MemoryStream(privateKeyBits))) - //{ - // byte bt = 0; - // ushort twobytes = 0; - // twobytes = binr.ReadUInt16(); - // if (twobytes == 0x8130) - // { - // binr.ReadByte(); - // } - // else if (twobytes == 0x8230) - // { - // binr.ReadInt16(); - // } - // else - // { - // throw new Exception("Unexpected value read binr.ReadUInt16()"); - // } - // twobytes = binr.ReadUInt16(); - // if (twobytes != 0x0102) - // { - // throw new Exception("Unexpected version"); - // } - // bt = binr.ReadByte(); - // if (bt != 0x00) - // { - // throw new Exception("Unexpected value read binr.ReadByte()"); - // } - // rsaParams.Modulus = binr.ReadBytes(GetIntegerSize(binr)); - // rsaParams.Exponent = binr.ReadBytes(GetIntegerSize(binr)); - // rsaParams.D = binr.ReadBytes(GetIntegerSize(binr)); - // rsaParams.P = binr.ReadBytes(GetIntegerSize(binr)); - // rsaParams.Q = binr.ReadBytes(GetIntegerSize(binr)); - // rsaParams.DP = binr.ReadBytes(GetIntegerSize(binr)); - // rsaParams.DQ = binr.ReadBytes(GetIntegerSize(binr)); - // rsaParams.InverseQ = binr.ReadBytes(GetIntegerSize(binr)); - //} - //rsa.ImportParameters(rsaParams); - //return rsa; - #endregion - } - #endregion - /// TLV格式化(flag+长度数据占用位数+长度数值+数据) - /// - /// 标志 - /// - /// - private static List TLVFormat(byte flag, byte[] content) - { - var tlvBytes = new List - { - flag - }; - var contentLength = content.Length; - //判断是否需要添加0x00 - if (content[0] >= 0x80) - { - contentLength++; - } - //长度小于0x80(128,因为byte最大表示0-127),数据长度占用位没有了 - if (contentLength >= 0x80) - { - //小于256,0xFF=255 - if (contentLength <= 0xFF) - { - tlvBytes.Add(0x81); - tlvBytes.Add((byte)contentLength); - } - else - { - tlvBytes.Add(0x82); - var lengthBytes = BitConverter.GetBytes((ushort)contentLength).Reverse(); - tlvBytes.AddRange(lengthBytes); - } - } - else - { - //长度小于128,直接添加1位的长度 - tlvBytes.Add((byte)contentLength); - } - //判断是否需要添加0x00 - if (content[0] >= 0x80) - { - tlvBytes.Add(0x00); - } - //添加内容 - tlvBytes.AddRange(content); - return tlvBytes; - } - - /// 读取TLV结构中的数据 - /// - private static Span ReadTLV(Span tlvSpan) - { - //长度 - int length; - Span contentSpan; - //如果该值小于0x80,代表没有长度占用位 - if (tlvSpan[1] < 0x80) - { - length = tlvSpan[1]; - contentSpan = tlvSpan.Slice(2, length); - } - else if (tlvSpan[1] == 0x81) - { - length = tlvSpan[2]; - contentSpan = tlvSpan.Slice(3, length); - } - else if (tlvSpan[1] == 0x82) - { - var lengthSpan = tlvSpan.Slice(2, 2); - lengthSpan.Reverse(); - length = BitConverter.ToUInt16(lengthSpan.ToArray(), 0); - contentSpan = tlvSpan.Slice(4, length); - } - else - { - throw new ArgumentException("TLV长度占用位不正确,应为0x81或者0x82"); - } - return contentSpan; - } - - /// 分割多个TLV格式数据,返回数据列表 - /// - private static List SplitTLVs(Span tlvs) - { - var tlvList = new List(); - var tlvSpan = tlvs.Slice(0); - var readLength = 0; - while (readLength < tlvs.Length) - { - //长度 - int length; - //当前Item的长度 - int itemLength = 1; - Span contentSpan; - //如果该值小于0x80,代表没有长度占用位 - if (tlvSpan[1] < 0x80) - { - length = tlvSpan[1]; - contentSpan = tlvSpan.Slice(2, length); - itemLength += 1; - } - else if (tlvSpan[1] == 0x81) - { - length = tlvSpan[2]; - contentSpan = tlvSpan.Slice(3, length); - itemLength += 2; - } - else if (tlvSpan[1] == 0x82) - { - //长度占用2个字节 - var lengthSpan = tlvSpan.Slice(2, 2); - lengthSpan.Reverse(); - length = BitConverter.ToUInt16(lengthSpan.ToArray(), 0); - contentSpan = tlvSpan.Slice(4, length); - itemLength += 3; - } - else - { - throw new ArgumentException("TLV长度占用位不正确,应为0x81或者0x82"); - } - tlvList.Add(contentSpan.ToArray()); - itemLength += length; - tlvSpan = tlvSpan.Slice(itemLength); - readLength += itemLength; - } - return tlvList; - } - - /// 读取内容数据 - /// - private static Span ReadContent(Span contentSpan) - { - if (contentSpan[0] == 0x00) - { - if (contentSpan[1] < 0x80) - { - throw new ArgumentException("RSA读取内容数据首位小于0x80不需要补0x00"); - } - return contentSpan.Slice(1); - } - else - { - return contentSpan.Slice(0); - } - } - } - - /// RSA私钥编码格式 - /// - public enum RSAKeyFormat - { - /// PKCS1 - /// - PKCS1 = 1, - - /// PKCS8 - /// - PKCS8 = 2, - - /// 未知 - /// - Unknow = 4 - } - - /// RSA密钥对 - /// - public class RSAKeyPair : IEquatable - { - /// 公钥 - /// - public string PublicKey { get; set; } - - /// 私钥 - /// - public string PrivateKey { get; set; } - - /// Ctor - /// - public RSAKeyPair() - { - - } - - /// Ctor - /// - public RSAKeyPair(string publicKey, string privateKey) - { - PublicKey = publicKey; - PrivateKey = privateKey; - } - - /// 是否相同 - /// - public bool Equals(RSAKeyPair other) - { - return other.PrivateKey == PrivateKey && other.PublicKey == PublicKey; - } } - - } diff --git a/test/DotCommon.Test/Encrypt/Netstandard2RSAHelperTest.cs b/test/DotCommon.Test/Encrypt/Netstandard2RSAHelperTest.cs new file mode 100644 index 0000000..d9c822c --- /dev/null +++ b/test/DotCommon.Test/Encrypt/Netstandard2RSAHelperTest.cs @@ -0,0 +1,131 @@ +using DotCommon.Encrypt; +using System; +using System.Collections.Generic; +using System.Security.Cryptography; +using System.Text; +using Xunit; + +namespace DotCommon.Test.Encrypt +{ + public class Netstandard2RSAHelperTest + { + [Fact] + public void GenerateKeyPair_Test() + { + var keyPair = Netstandard2RSAHelper.GenerateKeyPair(RSAKeyFormat.PKCS1, 512); + + Assert.NotEmpty(keyPair.PublicKey); + var encrypted1 = Netstandard2RSAHelper.EncryptAsBase64("hello", keyPair.PublicKey); + var decrypted1 = Netstandard2RSAHelper.DecryptFromBase64(encrypted1, keyPair.PrivateKey); + Assert.Equal("hello", decrypted1); + + var signed1 = Netstandard2RSAHelper.SignDataAsBase64("string1", keyPair.PrivateKey); + Assert.True(Netstandard2RSAHelper.VerifyBase64Data("string1", signed1, keyPair.PublicKey)); + + + var rsaParams1 = Netstandard2RSAHelper.ReadPrivateKeyInfo(keyPair.PrivateKey); + + var rsaParams2 = Netstandard2RSAHelper.ReadPrivateKeyInfo(keyPair.PrivateKey); + var rsaPrivateKey2 = Netstandard2RSAHelper.ExportPrivateKeyPKCS1(rsaParams1); + var rsaPrivateKey3 = Netstandard2RSAHelper.ExportPrivateKeyPKCS8(rsaParams2); + + var decrypted2 = Netstandard2RSAHelper.DecryptFromBase64(encrypted1, rsaPrivateKey2); + var decrypted3 = Netstandard2RSAHelper.DecryptFromBase64(encrypted1, rsaPrivateKey3); + Assert.Equal("hello", decrypted2); + Assert.Equal("hello", decrypted3); + + } + + [Fact] + public void KeyPair_Equal_Test() + { + var keyPair = Netstandard2RSAHelper.GenerateKeyPair(RSAKeyFormat.PKCS8, 2048); + var keyPair2 = new RSAKeyPair() + { + PrivateKey = keyPair.PrivateKey, + PublicKey = keyPair.PublicKey + }; + + Assert.Equal(keyPair, keyPair2); + } + + + + + /// PKCS1与PKCS8密钥转换 + /// + [Fact] + public void PKCS8_PKCS1_Conver_Test() + { + var keyPair1 = Netstandard2RSAHelper.GenerateKeyPair(RSAKeyFormat.PKCS1); + var pkcs8Key1 = Netstandard2RSAHelper.PKCS1ToPKCS8(keyPair1.PrivateKey); + + var encrypted1 = Netstandard2RSAHelper.EncryptAsBase64("123456", keyPair1.PublicKey); + + var decrypted1 = Netstandard2RSAHelper.DecryptFromBase64(encrypted1, keyPair1.PrivateKey); + Assert.Equal("123456", decrypted1); + var decrypted2 = Netstandard2RSAHelper.DecryptFromBase64(encrypted1, pkcs8Key1); + Assert.Equal("123456", decrypted2); + + var pkcs1Key = Netstandard2RSAHelper.PKCS8ToPKCS1(pkcs8Key1); + Assert.Equal(keyPair1.PrivateKey, pkcs1Key); + } + + + [Fact] + public void PKCS8KeyPair_Generate_Test() + { + var keyPair = Netstandard2RSAHelper.GenerateKeyPair(RSAKeyFormat.PKCS8); + var pkcs1Key = Netstandard2RSAHelper.PKCS8ToPKCS1(keyPair.PrivateKey); + var pkcs8Key = Netstandard2RSAHelper.PKCS1ToPKCS8(pkcs1Key); + Assert.Equal(pkcs8Key, keyPair.PrivateKey); + } + + + + [Fact] + public void Encrypt_Decrypt_Test() + { + var privateKey1 = @"MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCiK5yWdMkJK+H/vyWT0W8pNUYDVFuAlDWOWLBbXA1ZI+Rq38Q0m6njnAnHJ2XKSwujlXwtyJ4vDZdk9LF9H5NIt1njS9NG0JKh+sdrMIfyUPagKdWcT+gsl5zD3ifnVYsKJU5ZyDLo9X4zmXQS67JAp+aQKU1YKxoHqgfg+lEXm2jdJNrynWE6vDMWeuixXayGlOK4f82tR3zS4WKdr3lrG5PqUWjAYBFp+wsAE+rhFCvsk3iOwqUSL2H0Xm8aAKeyMqQ5aC6XC2tPFV91oeHv0jIYQGN3WcT/loFNbgmIduNgXzMHGCwA6PbIMvmQsPMieueLyI/gptcJ1KAQ7DmXAgMBAAECggEAdM2anBeDkNKFlbG0PBJ10SVoxw8kVKjrJhqk8ziK+LBMXdnLtOSFacXCmSm8PAbvXCRX65X6sQNGDtXbXLa4W4CMApVjmDaz1m0M4xxyXkqIR/W5wDshi7SrmbvR2+IWIfmaxDnYyUfAXSPioZoXqlAEVcMZzS5GMkz6HcXNUIVcLTPSI8g9DgjKN11jhhBFEi4qMN7IdwmVrGLHpAzuzXN2EXBjLadt3Dg0RqT43a/+2OGN6YY+UcfZ/VSA3Y85PD0vRVhp4corZPp4hRinGdNzjImAMrx6RWq/Uz9SmijJEI3yhRd+zoqFipDESVJqutfvMNwIY6PLw6JDntL2mQKBgQDmqnQWND8dPu1ox141P5gRQX5pm/n057MhS3NddyyDOjoGZyibIGujzSIGCCTYBInIU1oGGkyOxU6h999U2g7l0H4ATnAuZCO9LxyAZonLO9HKK09U43os/fYL/vWEkCXsVX1is6P2VqYBiYbj2acY36CO7JgZX43q7M5ZfNxclQKBgQCz+0vLSrOgBbvAuZ5hTghtZBpTvRqdIb6Gol2Beh2HZ8fSSWzMWwPOXMJeYRTDcBhoh3Be7ilCoucYt6ITroVxUJWdo96xrC1Qv+tZHrfKPd3O43jdhvp2D9zyVlYrI83lmVwYK1p1v2JESOTD8jbynx9t1tfF4JX7vcHXkQ9GewKBgQDA95QKB0dNhhlCcJcFYOAsf2frncrr8PHQRriKVmpslcd5F8/GhsbFz5RJC4MXHCTP67sCI/or7jAsG5s/9vRDmbnvM69xf+DOIZ1sZVudI7wLr1O8pljNTuAJhQ+MCLNRFOvCKJpgOHjEDHNGJg0+J8bACnnrsB6fi9/MyUHoSQKBgCzX+x2O4kyHwS0W0qB5+d2PqIOexWfLRZZ0FAozq/HV6NK7WrFcKAmd0QwE8lBzuJEq1dPBUWR6BEyDTI3M2RDPvEeH0e/A75WEDBarca2hVoe6452GiRcrgqia3GNpS17epDSdcK+P3OMYqm8sBYbUINeURTTXbWdI82hLi1vLAoGBAOX1RCqZpbLF/SNCT3BBcib/DmfZ7R1Rym5ZfYCfd3Wv478Inuhp4UraCTtwMnGrgJh5uQIGe7GCN7w1zA8w59/EtMknYWdMhBV3MRTr/b72uFf0ZQeeJYD/VX6LMRsxX/bWCrxB0McLcLHOevRXFAgOk4ymc1YuWhNZT2x9qBEC"; + var publicKey1 = @"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoiuclnTJCSvh/78lk9FvKTVGA1RbgJQ1jliwW1wNWSPkat/ENJup45wJxydlyksLo5V8LcieLw2XZPSxfR+TSLdZ40vTRtCSofrHazCH8lD2oCnVnE/oLJecw94n51WLCiVOWcgy6PV+M5l0EuuyQKfmkClNWCsaB6oH4PpRF5to3STa8p1hOrwzFnrosV2shpTiuH/NrUd80uFina95axuT6lFowGARafsLABPq4RQr7JN4jsKlEi9h9F5vGgCnsjKkOWgulwtrTxVfdaHh79IyGEBjd1nE/5aBTW4JiHbjYF8zBxgsAOj2yDL5kLDzInrni8iP4KbXCdSgEOw5lwIDAQAB"; + + var str = "HelloWorld!"; + var encrypted1 = Netstandard2RSAHelper.EncryptAsBase64(str, publicKey1, RSAEncryptionPadding.Pkcs1); + var decrypted1 = Netstandard2RSAHelper.DecryptFromBase64(encrypted1, privateKey1, RSAEncryptionPadding.Pkcs1); + Assert.Equal(str, decrypted1); + + } + + [Fact] + public void Sign_VerifySign_Test() + { + var str = "你好,中国!"; + var privateKey1 = @"MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCiK5yWdMkJK+H/vyWT0W8pNUYDVFuAlDWOWLBbXA1ZI+Rq38Q0m6njnAnHJ2XKSwujlXwtyJ4vDZdk9LF9H5NIt1njS9NG0JKh+sdrMIfyUPagKdWcT+gsl5zD3ifnVYsKJU5ZyDLo9X4zmXQS67JAp+aQKU1YKxoHqgfg+lEXm2jdJNrynWE6vDMWeuixXayGlOK4f82tR3zS4WKdr3lrG5PqUWjAYBFp+wsAE+rhFCvsk3iOwqUSL2H0Xm8aAKeyMqQ5aC6XC2tPFV91oeHv0jIYQGN3WcT/loFNbgmIduNgXzMHGCwA6PbIMvmQsPMieueLyI/gptcJ1KAQ7DmXAgMBAAECggEAdM2anBeDkNKFlbG0PBJ10SVoxw8kVKjrJhqk8ziK+LBMXdnLtOSFacXCmSm8PAbvXCRX65X6sQNGDtXbXLa4W4CMApVjmDaz1m0M4xxyXkqIR/W5wDshi7SrmbvR2+IWIfmaxDnYyUfAXSPioZoXqlAEVcMZzS5GMkz6HcXNUIVcLTPSI8g9DgjKN11jhhBFEi4qMN7IdwmVrGLHpAzuzXN2EXBjLadt3Dg0RqT43a/+2OGN6YY+UcfZ/VSA3Y85PD0vRVhp4corZPp4hRinGdNzjImAMrx6RWq/Uz9SmijJEI3yhRd+zoqFipDESVJqutfvMNwIY6PLw6JDntL2mQKBgQDmqnQWND8dPu1ox141P5gRQX5pm/n057MhS3NddyyDOjoGZyibIGujzSIGCCTYBInIU1oGGkyOxU6h999U2g7l0H4ATnAuZCO9LxyAZonLO9HKK09U43os/fYL/vWEkCXsVX1is6P2VqYBiYbj2acY36CO7JgZX43q7M5ZfNxclQKBgQCz+0vLSrOgBbvAuZ5hTghtZBpTvRqdIb6Gol2Beh2HZ8fSSWzMWwPOXMJeYRTDcBhoh3Be7ilCoucYt6ITroVxUJWdo96xrC1Qv+tZHrfKPd3O43jdhvp2D9zyVlYrI83lmVwYK1p1v2JESOTD8jbynx9t1tfF4JX7vcHXkQ9GewKBgQDA95QKB0dNhhlCcJcFYOAsf2frncrr8PHQRriKVmpslcd5F8/GhsbFz5RJC4MXHCTP67sCI/or7jAsG5s/9vRDmbnvM69xf+DOIZ1sZVudI7wLr1O8pljNTuAJhQ+MCLNRFOvCKJpgOHjEDHNGJg0+J8bACnnrsB6fi9/MyUHoSQKBgCzX+x2O4kyHwS0W0qB5+d2PqIOexWfLRZZ0FAozq/HV6NK7WrFcKAmd0QwE8lBzuJEq1dPBUWR6BEyDTI3M2RDPvEeH0e/A75WEDBarca2hVoe6452GiRcrgqia3GNpS17epDSdcK+P3OMYqm8sBYbUINeURTTXbWdI82hLi1vLAoGBAOX1RCqZpbLF/SNCT3BBcib/DmfZ7R1Rym5ZfYCfd3Wv478Inuhp4UraCTtwMnGrgJh5uQIGe7GCN7w1zA8w59/EtMknYWdMhBV3MRTr/b72uFf0ZQeeJYD/VX6LMRsxX/bWCrxB0McLcLHOevRXFAgOk4ymc1YuWhNZT2x9qBEC"; + var publicKey1 = @"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoiuclnTJCSvh/78lk9FvKTVGA1RbgJQ1jliwW1wNWSPkat/ENJup45wJxydlyksLo5V8LcieLw2XZPSxfR+TSLdZ40vTRtCSofrHazCH8lD2oCnVnE/oLJecw94n51WLCiVOWcgy6PV+M5l0EuuyQKfmkClNWCsaB6oH4PpRF5to3STa8p1hOrwzFnrosV2shpTiuH/NrUd80uFina95axuT6lFowGARafsLABPq4RQr7JN4jsKlEi9h9F5vGgCnsjKkOWgulwtrTxVfdaHh79IyGEBjd1nE/5aBTW4JiHbjYF8zBxgsAOj2yDL5kLDzInrni8iP4KbXCdSgEOw5lwIDAQAB"; + + var signed1 = Netstandard2RSAHelper.SignDataAsBase64(str, privateKey1, RSASignaturePadding.Pkcs1); + + Assert.True(Netstandard2RSAHelper.VerifyBase64Data(str, signed1, publicKey1)); + } + + [Fact] + public void GetKeyFormat_Test() + { + var privateKey1 = @"MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCiK5yWdMkJK+H/vyWT0W8pNUYDVFuAlDWOWLBbXA1ZI+Rq38Q0m6njnAnHJ2XKSwujlXwtyJ4vDZdk9LF9H5NIt1njS9NG0JKh+sdrMIfyUPagKdWcT+gsl5zD3ifnVYsKJU5ZyDLo9X4zmXQS67JAp+aQKU1YKxoHqgfg+lEXm2jdJNrynWE6vDMWeuixXayGlOK4f82tR3zS4WKdr3lrG5PqUWjAYBFp+wsAE+rhFCvsk3iOwqUSL2H0Xm8aAKeyMqQ5aC6XC2tPFV91oeHv0jIYQGN3WcT/loFNbgmIduNgXzMHGCwA6PbIMvmQsPMieueLyI/gptcJ1KAQ7DmXAgMBAAECggEAdM2anBeDkNKFlbG0PBJ10SVoxw8kVKjrJhqk8ziK+LBMXdnLtOSFacXCmSm8PAbvXCRX65X6sQNGDtXbXLa4W4CMApVjmDaz1m0M4xxyXkqIR/W5wDshi7SrmbvR2+IWIfmaxDnYyUfAXSPioZoXqlAEVcMZzS5GMkz6HcXNUIVcLTPSI8g9DgjKN11jhhBFEi4qMN7IdwmVrGLHpAzuzXN2EXBjLadt3Dg0RqT43a/+2OGN6YY+UcfZ/VSA3Y85PD0vRVhp4corZPp4hRinGdNzjImAMrx6RWq/Uz9SmijJEI3yhRd+zoqFipDESVJqutfvMNwIY6PLw6JDntL2mQKBgQDmqnQWND8dPu1ox141P5gRQX5pm/n057MhS3NddyyDOjoGZyibIGujzSIGCCTYBInIU1oGGkyOxU6h999U2g7l0H4ATnAuZCO9LxyAZonLO9HKK09U43os/fYL/vWEkCXsVX1is6P2VqYBiYbj2acY36CO7JgZX43q7M5ZfNxclQKBgQCz+0vLSrOgBbvAuZ5hTghtZBpTvRqdIb6Gol2Beh2HZ8fSSWzMWwPOXMJeYRTDcBhoh3Be7ilCoucYt6ITroVxUJWdo96xrC1Qv+tZHrfKPd3O43jdhvp2D9zyVlYrI83lmVwYK1p1v2JESOTD8jbynx9t1tfF4JX7vcHXkQ9GewKBgQDA95QKB0dNhhlCcJcFYOAsf2frncrr8PHQRriKVmpslcd5F8/GhsbFz5RJC4MXHCTP67sCI/or7jAsG5s/9vRDmbnvM69xf+DOIZ1sZVudI7wLr1O8pljNTuAJhQ+MCLNRFOvCKJpgOHjEDHNGJg0+J8bACnnrsB6fi9/MyUHoSQKBgCzX+x2O4kyHwS0W0qB5+d2PqIOexWfLRZZ0FAozq/HV6NK7WrFcKAmd0QwE8lBzuJEq1dPBUWR6BEyDTI3M2RDPvEeH0e/A75WEDBarca2hVoe6452GiRcrgqia3GNpS17epDSdcK+P3OMYqm8sBYbUINeURTTXbWdI82hLi1vLAoGBAOX1RCqZpbLF/SNCT3BBcib/DmfZ7R1Rym5ZfYCfd3Wv478Inuhp4UraCTtwMnGrgJh5uQIGe7GCN7w1zA8w59/EtMknYWdMhBV3MRTr/b72uFf0ZQeeJYD/VX6LMRsxX/bWCrxB0McLcLHOevRXFAgOk4ymc1YuWhNZT2x9qBEC"; + + var privateKey2 = @"MIIEpAIBAAKCAQEAoiuclnTJCSvh/78lk9FvKTVGA1RbgJQ1jliwW1wNWSPkat/ENJup45wJxydlyksLo5V8LcieLw2XZPSxfR+TSLdZ40vTRtCSofrHazCH8lD2oCnVnE/oLJecw94n51WLCiVOWcgy6PV+M5l0EuuyQKfmkClNWCsaB6oH4PpRF5to3STa8p1hOrwzFnrosV2shpTiuH/NrUd80uFina95axuT6lFowGARafsLABPq4RQr7JN4jsKlEi9h9F5vGgCnsjKkOWgulwtrTxVfdaHh79IyGEBjd1nE/5aBTW4JiHbjYF8zBxgsAOj2yDL5kLDzInrni8iP4KbXCdSgEOw5lwIDAQABAoIBAHTNmpwXg5DShZWxtDwSddElaMcPJFSo6yYapPM4iviwTF3Zy7TkhWnFwpkpvDwG71wkV+uV+rEDRg7V21y2uFuAjAKVY5g2s9ZtDOMccl5KiEf1ucA7IYu0q5m70dviFiH5msQ52MlHwF0j4qGaF6pQBFXDGc0uRjJM+h3FzVCFXC0z0iPIPQ4IyjddY4YQRRIuKjDeyHcJlaxix6QM7s1zdhFwYy2nbdw4NEak+N2v/tjhjemGPlHH2f1UgN2POTw9L0VYaeHKK2T6eIUYpxnTc4yJgDK8ekVqv1M/UpooyRCN8oUXfs6KhYqQxElSarrX7zDcCGOjy8OiQ57S9pkCgYEA5qp0FjQ/HT7taMdeNT+YEUF+aZv59OezIUtzXXcsgzo6BmcomyBro80iBggk2ASJyFNaBhpMjsVOofffVNoO5dB+AE5wLmQjvS8cgGaJyzvRyitPVON6LP32C/71hJAl7FV9YrOj9lamAYmG49mnGN+gjuyYGV+N6uzOWXzcXJUCgYEAs/tLy0qzoAW7wLmeYU4IbWQaU70anSG+hqJdgXodh2fH0klszFsDzlzCXmEUw3AYaIdwXu4pQqLnGLeiE66FcVCVnaPesawtUL/rWR63yj3dzuN43Yb6dg/c8lZWKyPN5ZlcGCtadb9iREjkw/I28p8fbdbXxeCV+73B15EPRnsCgYEAwPeUCgdHTYYZQnCXBWDgLH9n653K6/Dx0Ea4ilZqbJXHeRfPxobGxc+USQuDFxwkz+u7AiP6K+4wLBubP/b0Q5m57zOvcX/gziGdbGVbnSO8C69TvKZYzU7gCYUPjAizURTrwiiaYDh4xAxzRiYNPifGwAp567Aen4vfzMlB6EkCgYAs1/sdjuJMh8EtFtKgefndj6iDnsVny0WWdBQKM6vx1ejSu1qxXCgJndEMBPJQc7iRKtXTwVFkegRMg0yNzNkQz7xHh9HvwO+VhAwWq3GtoVaHuuOdhokXK4KomtxjaUte3qQ0nXCvj9zjGKpvLAWG1CDXlEU0121nSPNoS4tbywKBgQDl9UQqmaWyxf0jQk9wQXIm/w5n2e0dUcpuWX2An3d1r+O/CJ7oaeFK2gk7cDJxq4CYebkCBnuxgje8NcwPMOffxLTJJ2FnTIQVdzEU6/2+9rhX9GUHniWA/1V+izEbMV/21gq8QdDHC3Cxznr0VxQIDpOMpnNWLloTWU9sfagRAg=="; + + var format1 = Netstandard2RSAHelper.GetKeyFormat(privateKey1); + Assert.Equal(RSAKeyFormat.PKCS8, format1); + + var format2 = Netstandard2RSAHelper.GetKeyFormat(privateKey2); + Assert.Equal(RSAKeyFormat.PKCS1, format2); + + //var format3 = RSAHelper.GetKeyFormat("xxxqqqq"); + //Assert.Equal(RSAKeyFormat.Unknow, format3); + + + } + + } +} diff --git a/test/DotCommon.Test/Encrypt/RSAHelperTest.cs b/test/DotCommon.Test/Encrypt/RSAHelperTest.cs index e7324fe..dd29a42 100644 --- a/test/DotCommon.Test/Encrypt/RSAHelperTest.cs +++ b/test/DotCommon.Test/Encrypt/RSAHelperTest.cs @@ -21,19 +21,6 @@ public void GenerateKeyPair_Test() var signed1 = RSAHelper.SignDataAsBase64("string1", keyPair.PrivateKey); Assert.True(RSAHelper.VerifyBase64Data("string1", signed1, keyPair.PublicKey)); - - - var rsaParams1 = RSAHelper.ReadPrivateKeyInfo(keyPair.PrivateKey); - - var rsaParams2 = RSAHelper.ReadPrivateKeyInfo(keyPair.PrivateKey); - var rsaPrivateKey2 = RSAHelper.ExportPrivateKeyPKCS1(rsaParams1); - var rsaPrivateKey3 = RSAHelper.ExportPrivateKeyPKCS8(rsaParams2); - - var decrypted2 = RSAHelper.DecryptFromBase64(encrypted1, rsaPrivateKey2); - var decrypted3 = RSAHelper.DecryptFromBase64(encrypted1, rsaPrivateKey3); - Assert.Equal("hello", decrypted2); - Assert.Equal("hello", decrypted3); - } [Fact] @@ -64,8 +51,6 @@ public void PKCS8_PKCS1_Conver_Test() var decrypted1 = RSAHelper.DecryptFromBase64(encrypted1, keyPair1.PrivateKey); Assert.Equal("123456", decrypted1); - var decrypted2 = RSAHelper.DecryptFromBase64(encrypted1, pkcs8Key1); - Assert.Equal("123456", decrypted2); var pkcs1Key = RSAHelper.PKCS8ToPKCS1(pkcs8Key1); Assert.Equal(keyPair1.PrivateKey, pkcs1Key); @@ -90,8 +75,8 @@ public void Encrypt_Decrypt_Test() var publicKey1 = @"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoiuclnTJCSvh/78lk9FvKTVGA1RbgJQ1jliwW1wNWSPkat/ENJup45wJxydlyksLo5V8LcieLw2XZPSxfR+TSLdZ40vTRtCSofrHazCH8lD2oCnVnE/oLJecw94n51WLCiVOWcgy6PV+M5l0EuuyQKfmkClNWCsaB6oH4PpRF5to3STa8p1hOrwzFnrosV2shpTiuH/NrUd80uFina95axuT6lFowGARafsLABPq4RQr7JN4jsKlEi9h9F5vGgCnsjKkOWgulwtrTxVfdaHh79IyGEBjd1nE/5aBTW4JiHbjYF8zBxgsAOj2yDL5kLDzInrni8iP4KbXCdSgEOw5lwIDAQAB"; var str = "HelloWorld!"; - var encrypted1 = RSAHelper.EncryptAsBase64(str, publicKey1, RSAEncryptionPadding.Pkcs1); - var decrypted1 = RSAHelper.DecryptFromBase64(encrypted1, privateKey1, RSAEncryptionPadding.Pkcs1); + var encrypted1 = Netstandard2RSAHelper.EncryptAsBase64(str, publicKey1, RSAEncryptionPadding.Pkcs1); + var decrypted1 = Netstandard2RSAHelper.DecryptFromBase64(encrypted1, privateKey1, RSAEncryptionPadding.Pkcs1); Assert.Equal(str, decrypted1); } @@ -103,9 +88,9 @@ public void Sign_VerifySign_Test() var privateKey1 = @"MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCiK5yWdMkJK+H/vyWT0W8pNUYDVFuAlDWOWLBbXA1ZI+Rq38Q0m6njnAnHJ2XKSwujlXwtyJ4vDZdk9LF9H5NIt1njS9NG0JKh+sdrMIfyUPagKdWcT+gsl5zD3ifnVYsKJU5ZyDLo9X4zmXQS67JAp+aQKU1YKxoHqgfg+lEXm2jdJNrynWE6vDMWeuixXayGlOK4f82tR3zS4WKdr3lrG5PqUWjAYBFp+wsAE+rhFCvsk3iOwqUSL2H0Xm8aAKeyMqQ5aC6XC2tPFV91oeHv0jIYQGN3WcT/loFNbgmIduNgXzMHGCwA6PbIMvmQsPMieueLyI/gptcJ1KAQ7DmXAgMBAAECggEAdM2anBeDkNKFlbG0PBJ10SVoxw8kVKjrJhqk8ziK+LBMXdnLtOSFacXCmSm8PAbvXCRX65X6sQNGDtXbXLa4W4CMApVjmDaz1m0M4xxyXkqIR/W5wDshi7SrmbvR2+IWIfmaxDnYyUfAXSPioZoXqlAEVcMZzS5GMkz6HcXNUIVcLTPSI8g9DgjKN11jhhBFEi4qMN7IdwmVrGLHpAzuzXN2EXBjLadt3Dg0RqT43a/+2OGN6YY+UcfZ/VSA3Y85PD0vRVhp4corZPp4hRinGdNzjImAMrx6RWq/Uz9SmijJEI3yhRd+zoqFipDESVJqutfvMNwIY6PLw6JDntL2mQKBgQDmqnQWND8dPu1ox141P5gRQX5pm/n057MhS3NddyyDOjoGZyibIGujzSIGCCTYBInIU1oGGkyOxU6h999U2g7l0H4ATnAuZCO9LxyAZonLO9HKK09U43os/fYL/vWEkCXsVX1is6P2VqYBiYbj2acY36CO7JgZX43q7M5ZfNxclQKBgQCz+0vLSrOgBbvAuZ5hTghtZBpTvRqdIb6Gol2Beh2HZ8fSSWzMWwPOXMJeYRTDcBhoh3Be7ilCoucYt6ITroVxUJWdo96xrC1Qv+tZHrfKPd3O43jdhvp2D9zyVlYrI83lmVwYK1p1v2JESOTD8jbynx9t1tfF4JX7vcHXkQ9GewKBgQDA95QKB0dNhhlCcJcFYOAsf2frncrr8PHQRriKVmpslcd5F8/GhsbFz5RJC4MXHCTP67sCI/or7jAsG5s/9vRDmbnvM69xf+DOIZ1sZVudI7wLr1O8pljNTuAJhQ+MCLNRFOvCKJpgOHjEDHNGJg0+J8bACnnrsB6fi9/MyUHoSQKBgCzX+x2O4kyHwS0W0qB5+d2PqIOexWfLRZZ0FAozq/HV6NK7WrFcKAmd0QwE8lBzuJEq1dPBUWR6BEyDTI3M2RDPvEeH0e/A75WEDBarca2hVoe6452GiRcrgqia3GNpS17epDSdcK+P3OMYqm8sBYbUINeURTTXbWdI82hLi1vLAoGBAOX1RCqZpbLF/SNCT3BBcib/DmfZ7R1Rym5ZfYCfd3Wv478Inuhp4UraCTtwMnGrgJh5uQIGe7GCN7w1zA8w59/EtMknYWdMhBV3MRTr/b72uFf0ZQeeJYD/VX6LMRsxX/bWCrxB0McLcLHOevRXFAgOk4ymc1YuWhNZT2x9qBEC"; var publicKey1 = @"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoiuclnTJCSvh/78lk9FvKTVGA1RbgJQ1jliwW1wNWSPkat/ENJup45wJxydlyksLo5V8LcieLw2XZPSxfR+TSLdZ40vTRtCSofrHazCH8lD2oCnVnE/oLJecw94n51WLCiVOWcgy6PV+M5l0EuuyQKfmkClNWCsaB6oH4PpRF5to3STa8p1hOrwzFnrosV2shpTiuH/NrUd80uFina95axuT6lFowGARafsLABPq4RQr7JN4jsKlEi9h9F5vGgCnsjKkOWgulwtrTxVfdaHh79IyGEBjd1nE/5aBTW4JiHbjYF8zBxgsAOj2yDL5kLDzInrni8iP4KbXCdSgEOw5lwIDAQAB"; - var signed1 = RSAHelper.SignDataAsBase64(str, privateKey1, RSASignaturePadding.Pkcs1); + var signed1 = Netstandard2RSAHelper.SignDataAsBase64(str, privateKey1, RSASignaturePadding.Pkcs1); - Assert.True(RSAHelper.VerifyBase64Data(str, signed1, publicKey1)); + Assert.True(Netstandard2RSAHelper.VerifyBase64Data(str, signed1, publicKey1)); } [Fact] @@ -115,10 +100,10 @@ public void GetKeyFormat_Test() var privateKey2 = @"MIIEpAIBAAKCAQEAoiuclnTJCSvh/78lk9FvKTVGA1RbgJQ1jliwW1wNWSPkat/ENJup45wJxydlyksLo5V8LcieLw2XZPSxfR+TSLdZ40vTRtCSofrHazCH8lD2oCnVnE/oLJecw94n51WLCiVOWcgy6PV+M5l0EuuyQKfmkClNWCsaB6oH4PpRF5to3STa8p1hOrwzFnrosV2shpTiuH/NrUd80uFina95axuT6lFowGARafsLABPq4RQr7JN4jsKlEi9h9F5vGgCnsjKkOWgulwtrTxVfdaHh79IyGEBjd1nE/5aBTW4JiHbjYF8zBxgsAOj2yDL5kLDzInrni8iP4KbXCdSgEOw5lwIDAQABAoIBAHTNmpwXg5DShZWxtDwSddElaMcPJFSo6yYapPM4iviwTF3Zy7TkhWnFwpkpvDwG71wkV+uV+rEDRg7V21y2uFuAjAKVY5g2s9ZtDOMccl5KiEf1ucA7IYu0q5m70dviFiH5msQ52MlHwF0j4qGaF6pQBFXDGc0uRjJM+h3FzVCFXC0z0iPIPQ4IyjddY4YQRRIuKjDeyHcJlaxix6QM7s1zdhFwYy2nbdw4NEak+N2v/tjhjemGPlHH2f1UgN2POTw9L0VYaeHKK2T6eIUYpxnTc4yJgDK8ekVqv1M/UpooyRCN8oUXfs6KhYqQxElSarrX7zDcCGOjy8OiQ57S9pkCgYEA5qp0FjQ/HT7taMdeNT+YEUF+aZv59OezIUtzXXcsgzo6BmcomyBro80iBggk2ASJyFNaBhpMjsVOofffVNoO5dB+AE5wLmQjvS8cgGaJyzvRyitPVON6LP32C/71hJAl7FV9YrOj9lamAYmG49mnGN+gjuyYGV+N6uzOWXzcXJUCgYEAs/tLy0qzoAW7wLmeYU4IbWQaU70anSG+hqJdgXodh2fH0klszFsDzlzCXmEUw3AYaIdwXu4pQqLnGLeiE66FcVCVnaPesawtUL/rWR63yj3dzuN43Yb6dg/c8lZWKyPN5ZlcGCtadb9iREjkw/I28p8fbdbXxeCV+73B15EPRnsCgYEAwPeUCgdHTYYZQnCXBWDgLH9n653K6/Dx0Ea4ilZqbJXHeRfPxobGxc+USQuDFxwkz+u7AiP6K+4wLBubP/b0Q5m57zOvcX/gziGdbGVbnSO8C69TvKZYzU7gCYUPjAizURTrwiiaYDh4xAxzRiYNPifGwAp567Aen4vfzMlB6EkCgYAs1/sdjuJMh8EtFtKgefndj6iDnsVny0WWdBQKM6vx1ejSu1qxXCgJndEMBPJQc7iRKtXTwVFkegRMg0yNzNkQz7xHh9HvwO+VhAwWq3GtoVaHuuOdhokXK4KomtxjaUte3qQ0nXCvj9zjGKpvLAWG1CDXlEU0121nSPNoS4tbywKBgQDl9UQqmaWyxf0jQk9wQXIm/w5n2e0dUcpuWX2An3d1r+O/CJ7oaeFK2gk7cDJxq4CYebkCBnuxgje8NcwPMOffxLTJJ2FnTIQVdzEU6/2+9rhX9GUHniWA/1V+izEbMV/21gq8QdDHC3Cxznr0VxQIDpOMpnNWLloTWU9sfagRAg=="; - var format1 = RSAHelper.GetKeyFormat(privateKey1); + var format1 = Netstandard2RSAHelper.GetKeyFormat(privateKey1); Assert.Equal(RSAKeyFormat.PKCS8, format1); - var format2 = RSAHelper.GetKeyFormat(privateKey2); + var format2 = Netstandard2RSAHelper.GetKeyFormat(privateKey2); Assert.Equal(RSAKeyFormat.PKCS1, format2); //var format3 = RSAHelper.GetKeyFormat("xxxqqqq"); @@ -126,6 +111,5 @@ public void GetKeyFormat_Test() } - } }