" + Convert.ToBase64String(Val_P) + "
"); + str.Append("" + Convert.ToBase64String(Val_Q) + ""); + str.Append("
+
+
# :open_book:文档
@@ -31,6 +39,16 @@
注:openssl `RSAPublicKey_out`导出的公钥,字节码内并不带[OID](http://www.oid-info.com/get/1.2.840.113549.1.1.1)(目测是因为不带OID所以openssl自己都不支持用这个公钥来加密数据),RSA_PEM支持此格式公钥的导入,但不提供此种格式公钥的导出。
+
+### 构造方法
+
+**RSA_PEM(RSACryptoServiceProvider rsa, bool convertToPublic = false)**:通过RSA中的公钥和私钥构造一个PEM,如果convertToPublic含私钥的RSA将只读取公钥,仅含公钥的RSA不受影响。
+
+**RSA_PEM(byte[] modulus, byte[] exponent, byte[] d, byte[] p, byte[] q, byte[] dp, byte[] dq, byte[] inverseQ)**:通过全量的PEM字段数据构造一个PEM,除了模数modulus和公钥指数exponent必须提供外,其他私钥指数信息要么全部提供,要么全部不提供(导出的PEM就只包含公钥)注意:所有参数首字节如果是0,必须先去掉。
+
+**RSA_PEM(byte[] modulus, byte[] exponent, byte[] dOrNull)**:通过公钥指数和私钥指数构造一个PEM,会反推计算出P、Q但和原始生成密钥的P、Q极小可能相同。注意:所有参数首字节如果是0,必须先去掉。出错将会抛出异常。私钥指数可以不提供,导出的PEM就只包含公钥。
+
+
### 实例属性
byte[]:**Key_Modulus**(模数n,公钥、私钥都有)、**Key_Exponent**(公钥指数e,公钥、私钥都有)、**Key_D**(私钥指数d,只有私钥的时候才有);有这3个足够用来加密解密。
@@ -41,14 +59,6 @@ int:**KeySize**(密钥位数)
bool:**HasPrivate**(是否包含私钥)
-### 构造方法
-
-**RSA_PEM(RSACryptoServiceProvider rsa, bool convertToPublic = false)**:通过RSA中的公钥和私钥构造一个PEM,如果convertToPublic含私钥的RSA将只读取公钥,仅含公钥的RSA不受影响。
-
-**RSA_PEM(byte[] modulus, byte[] exponent, byte[] d, byte[] p, byte[] q, byte[] dp, byte[] dq, byte[] inverseQ)**:通过全量的PEM字段数据构造一个PEM,除了模数modulus和公钥指数exponent必须提供外,其他私钥指数信息要么全部提供,要么全部不提供(导出的PEM就只包含公钥)注意:所有参数首字节如果是0,必须先去掉。
-
-**RSA_PEM(byte[] modulus, byte[] exponent, byte[] dOrNull)**:通过公钥指数和私钥指数构造一个PEM,会反推计算出P、Q但和原始生成密钥的P、Q极小可能相同。注意:所有参数首字节如果是0,必须先去掉。出错将会抛出异常。私钥指数可以不提供,导出的PEM就只包含公钥。
-
### 实例方法
From f0c8e019434e58a4492020e5c92ab84ca46c625c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=AB=98=E5=9D=9A=E6=9E=9C?= <753610399@qq.com>
Date: Wed, 29 Apr 2020 16:11:50 +0800
Subject: [PATCH 07/15] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=87=E6=A1=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/README.md b/README.md
index b9d7717..9a2bf91 100644
--- a/README.md
+++ b/README.md
@@ -411,3 +411,14 @@ openssl rsautl -decrypt -in data.enc.bin -inkey private.pem -out data.dec.txt
::因为这个公钥里面没有OID,通过RSA_PEM转换成PKCS#1自动带上OID就能正常加密
echo abcd123 | openssl rsautl -encrypt -inkey public.pem.rsakey -pubin
```
+
+
+
+
+# :star:捐赠
+如果这个库有帮助到您,请 Star 一下。
+
+您也可以使用支付宝或微信打赏作者:
+
+ 
+
From 68ef91d4559cca1161fb8877ecaa59de11849c1f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=AB=98=E5=9D=9A=E6=9E=9C?= <753610399@qq.com>
Date: Wed, 8 Jul 2020 22:34:21 +0800
Subject: [PATCH 08/15] =?UTF-8?q?=E5=8D=87=E7=BA=A71.2=E7=89=88=E6=9C=AC:?=
=?UTF-8?q?=20=E5=85=AC=E9=92=A5=E4=B9=9F=E5=8C=BA=E5=88=86PKCS#1=E5=92=8C?=
=?UTF-8?q?PKCS#8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Program.cs | 37 +++++++++++++--------
Properties/AssemblyInfo.cs | 4 +--
README.md | 59 ++++++++++++++++++++++++---------
RSA.cs | 30 ++++++++++-------
RSA_PEM.cs | 67 +++++++++++++++++++++++++++-----------
5 files changed, 136 insertions(+), 61 deletions(-)
diff --git a/Program.cs b/Program.cs
index b189c18..f2bd67e 100644
--- a/Program.cs
+++ b/Program.cs
@@ -11,11 +11,11 @@ static void RSATest() {
Console.WriteLine("【" + rsa.KeySize + "私钥(XML)】:");
Console.WriteLine(rsa.ToXML());
Console.WriteLine();
- Console.WriteLine("【" + rsa.KeySize + "私钥(PEM)】:");
- Console.WriteLine(rsa.ToPEM_PKCS1());
+ Console.WriteLine("【" + rsa.KeySize + "私钥(PKCS#1)】:");
+ Console.WriteLine(rsa.ToPEM().ToPEM_PKCS1());
Console.WriteLine();
- Console.WriteLine("【" + rsa.KeySize + "公钥(PEM)】:");
- Console.WriteLine(rsa.ToPEM_PKCS1(true));
+ Console.WriteLine("【" + rsa.KeySize + "公钥(PKCS#8)】:");
+ Console.WriteLine(rsa.ToPEM().ToPEM_PKCS8(true));
Console.WriteLine();
var str = "abc内容123";
@@ -30,33 +30,44 @@ static void RSATest() {
Console.WriteLine(rsa.Sign("SHA1", str));
Console.WriteLine();
- var rsa2 = new RSA(rsa.ToPEM_PKCS8(), true);
+ var rsa2 = new RSA(rsa.ToPEM().ToPEM_PKCS8(), true);
Console.WriteLine("【用PEM新创建的RSA是否和上面的一致】:");
Console.WriteLine("XML:" + (rsa2.ToXML() == rsa.ToXML()));
- Console.WriteLine("PKCS1:" + (rsa2.ToPEM_PKCS1() == rsa.ToPEM_PKCS1()));
- Console.WriteLine("PKCS8:" + (rsa2.ToPEM_PKCS8() == rsa.ToPEM_PKCS8()));
+ Console.WriteLine("PKCS1:" + (rsa2.ToPEM().ToPEM_PKCS1() == rsa.ToPEM().ToPEM_PKCS1()));
+ Console.WriteLine("PKCS8:" + (rsa2.ToPEM().ToPEM_PKCS8() == rsa.ToPEM().ToPEM_PKCS8()));
var rsa3 = new RSA(rsa.ToXML());
Console.WriteLine("【用XML新创建的RSA是否和上面的一致】:");
Console.WriteLine("XML:" + (rsa3.ToXML() == rsa.ToXML()));
- Console.WriteLine("PKCS1:" + (rsa3.ToPEM_PKCS1() == rsa.ToPEM_PKCS1()));
- Console.WriteLine("PKCS8:" + (rsa3.ToPEM_PKCS8() == rsa.ToPEM_PKCS8()));
+ Console.WriteLine("PKCS1:" + (rsa3.ToPEM().ToPEM_PKCS1() == rsa.ToPEM().ToPEM_PKCS1()));
+ Console.WriteLine("PKCS8:" + (rsa3.ToPEM().ToPEM_PKCS8() == rsa.ToPEM().ToPEM_PKCS8()));
//--------RSA_PEM验证---------
RSA_PEM pem = rsa.ToPEM();
Console.WriteLine("【RSA_PEM是否和原始RSA一致】:");
Console.WriteLine(pem.KeySize + "位");
Console.WriteLine("XML:" + (pem.ToXML(false) == rsa.ToXML()));
- Console.WriteLine("PKCS1:" + (pem.ToPEM(false, false) == rsa.ToPEM_PKCS1()));
- Console.WriteLine("PKCS8:" + (pem.ToPEM(false, true) == rsa.ToPEM_PKCS8()));
+ Console.WriteLine("PKCS1:" + (pem.ToPEM_PKCS1() == rsa.ToPEM().ToPEM_PKCS1()));
+ Console.WriteLine("PKCS8:" + (pem.ToPEM_PKCS8() == rsa.ToPEM().ToPEM_PKCS8()));
Console.WriteLine("仅公钥:");
Console.WriteLine("XML:" + (pem.ToXML(true) == rsa.ToXML(true)));
- Console.WriteLine("PKCS1:" + (pem.ToPEM(true, false) == rsa.ToPEM_PKCS1(true)));
- Console.WriteLine("PKCS8:" + (pem.ToPEM(true, true) == rsa.ToPEM_PKCS8(true)));
+ Console.WriteLine("PKCS1:" + (pem.ToPEM_PKCS1(true) == rsa.ToPEM().ToPEM_PKCS1(true)));
+ Console.WriteLine("PKCS8:" + (pem.ToPEM_PKCS8(true) == rsa.ToPEM().ToPEM_PKCS8(true)));
var rsa4 = new RSA(new RSA_PEM(pem.Key_Modulus, pem.Key_Exponent, pem.Key_D));
Console.WriteLine("【用n、e、d构造解密】");
Console.WriteLine(rsa4.DecodeOrNull(en));
+
+
+
+
+ Console.WriteLine();
+ Console.WriteLine();
+ Console.WriteLine("【" + rsa.KeySize + "私钥(PKCS#8)】:");
+ Console.WriteLine(rsa.ToPEM().ToPEM_PKCS8());
+ Console.WriteLine();
+ Console.WriteLine("【" + rsa.KeySize + "公钥(PKCS#1)】:不常见的公钥格式");
+ Console.WriteLine(rsa.ToPEM().ToPEM_PKCS1(true));
}
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
index 8d60d1b..2405ae3 100644
--- a/Properties/AssemblyInfo.cs
+++ b/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@
// 生成号
// 修订号
//
-[assembly: AssemblyVersion("1.1.0.0")]
-[assembly: AssemblyFileVersion("1.1.0.0")]
+[assembly: AssemblyVersion("1.2.0.0")]
+[assembly: AssemblyFileVersion("1.2.0.0")]
diff --git a/README.md b/README.md
index 9a2bf91..3f615bf 100644
--- a/README.md
+++ b/README.md
@@ -37,7 +37,7 @@
项目里面需要引入程序集`System.Numerics`用来支持`BigInteger`,vs默认创建的项目是不会自动引入此程序集的,要手动引入。
-注:openssl `RSAPublicKey_out`导出的公钥,字节码内并不带[OID](http://www.oid-info.com/get/1.2.840.113549.1.1.1)(目测是因为不带OID所以openssl自己都不支持用这个公钥来加密数据),RSA_PEM支持此格式公钥的导入,但不提供此种格式公钥的导出。
+注:`openssl rsa -in 私钥文件 -pubout`导出的是PKCS#8格式公钥(用的比较多),`openssl rsa -pubin -in PKCS#8公钥文件 -RSAPublicKey_out`导出的是PKCS#1格式公钥(用的比较少)。
### 构造方法
@@ -64,7 +64,11 @@ bool:**HasPrivate**(是否包含私钥)
**RSACryptoServiceProvider GetRSA()**:将PEM中的公钥私钥转成RSA对象,如果未提供私钥,RSA中就只包含公钥。
-**string ToPEM(bool convertToPublic, bool usePKCS8)**:将RSA中的密钥对转换成PEM格式,usePKCS8=false时返回PKCS#1格式,否则返回PKCS#8格式,如果convertToPublic含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响。
+**string ToPEM(bool convertToPublic, bool privateUsePKCS8, bool publicUsePKCS8)**:将RSA中的密钥对转换成PEM格式。convertToPublic:等于true时含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响 。**privateUsePKCS8**:私钥的返回格式,等于true时返回PKCS#8格式(`-----BEGIN PRIVATE KEY-----`),否则返回PKCS#1格式(`-----BEGIN RSA PRIVATE KEY-----`),返回公钥时此参数无效;两种格式使用都比较常见。**publicUsePKCS8**:公钥的返回格式,等于true时返回PKCS#8格式(`-----BEGIN PUBLIC KEY-----`),否则返回PKCS#1格式(`-----BEGIN RSA PUBLIC KEY-----`),返回私钥时此参数无效;一般用的多的是true PKCS#8格式公钥,PKCS#1格式公钥似乎比较少见。
+
+**string ToPEM_PKCS1(bool convertToPublic=false)**:ToPEM方法的简化写法,不管公钥还是私钥都返回PKCS#1格式;似乎导出PKCS#1公钥用的比较少,PKCS#8的公钥用的多些,私钥#1#8都差不多。
+
+**string ToPEM_PKCS8(bool convertToPublic=false)**:ToPEM方法的简化写法,不管公钥还是私钥都返回PKCS#8格式。
**string ToXML(bool convertToPublic)**:将RSA中的密钥对转换成XML格式,如果convertToPublic含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响。
@@ -91,6 +95,10 @@ bool:**HasPrivate**(是否包含私钥)
**RSA(RSA_PEM pem)**:通过一个pem对象创建RSA,pem为公钥或私钥,出错抛异常。
+**RSA(byte[] modulus, byte[] exponent, byte[] d, byte[] p, byte[] q, byte[] dp, byte[] dq, byte[] inverseQ)**:本方法会先生成RSA_PEM再创建RSA。通过全量的PEM字段数据构造一个PEM,除了模数modulus和公钥指数exponent必须提供外,其他私钥指数信息要么全部提供,要么全部不提供(导出的PEM就只包含公钥)注意:所有参数首字节如果是0,必须先去掉。
+
+**RSA(byte[] modulus, byte[] exponent, byte[] dOrNull)**:本方法会先生成RSA_PEM再创建RSA。通过公钥指数和私钥指数构造一个PEM,会反推计算出P、Q但和原始生成密钥的P、Q极小可能相同。注意:所有参数首字节如果是0,必须先去掉。出错将会抛出异常。私钥指数可以不提供,导出的PEM就只包含公钥。
+
### 实例属性
@@ -105,11 +113,7 @@ bool:**HasPrivate**(是否包含私钥)
**string ToXML(bool convertToPublic = false)**:导出`XML格式`秘钥对。如果RSA包含私钥,默认会导出私钥,设置仅仅导出公钥时只会导出公钥;不包含私钥只会导出公钥。
-**string ToPEM_PKCS1(bool convertToPublic = false)**:导出`PEM PKCS#1格式`秘钥对。如果RSA包含私钥,默认会导出私钥,设置仅仅导出公钥时只会导出公钥;不包含私钥只会导出公钥。
-
-**string ToPEM_PKCS8(bool convertToPublic = false)**:导出`PEM PKCS#8格式`秘钥对。如果RSA包含私钥,默认会导出私钥,设置仅仅导出公钥时只会导出公钥;不包含私钥只会导出公钥。
-
-**RSA_PEM ToPEM(bool convertToPublic = false)**:导出RSA_PEM对象,如果convertToPublic含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响。
+**RSA_PEM ToPEM(bool convertToPublic = false)**:导出RSA_PEM对象,如果convertToPublic含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响;通过RSA_PEM.ToPEM方法可以导出PEM文本。
**string Encode(string str)**:加密操作,支持任意长度数据。
@@ -189,11 +193,10 @@ PEM格式中,每段数据基本上都是`type+长度数据占用位数+长度
内容前面要加0(可能现在全部是加0吧,数据结尾这个字节不满8位?什么情况下会出现不够1字节?不够就用二进制0补齐,然后内容前面加补了几位)。
-### PEM公钥编码格式
-`PKCS#1`、`PKCS#8`公钥编码都是统一的格式。
+### PEM PKCS#8公钥编码格式
```
-/*****1024位公钥*****/
+/*****1024位PKCS#8公钥*****/
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYw9+M3+REzDtYqwBrs/as/Oy8
GRE5OmnqOV0EfkEiCIjiczbVEFnZ3qRjLbDATfmBxNQ6c6Fga8nX28glEH/aL/RG
@@ -201,7 +204,7 @@ GRE5OmnqOV0EfkEiCIjiczbVEFnZ3qRjLbDATfmBxNQ6c6Fga8nX28glEH/aL/RG
RWdNQlpIaTDo5IhJJwIDAQAB
-----END PUBLIC KEY-----
-/*****二进制表述*****/
+/*****二进制表述(文本是16进制下同)*****/
30819F300D06092A864886F70D010101050003818D003081890281810098C3DF8CDFE444CC3B58AB006BB3F6ACFCECBC1911393A69EA395D047E41220888E27336D51059D9DEA4632DB0C04DF981C4D43A73A1606BC9D7DBC825107FDA2FF446D8A76923C28C52A280B3337276C1D27A1F4C48A71DE73812E0DB84D2EF9E47B081F243968A988B0D0998DFC929337EA945674D425A486930E8E48849270203010001
@@ -221,7 +224,6 @@ RWdNQlpIaTDo5IhJJwIDAQAB
, 30_SEQUENCE:{
02_INTEGER: "整数"
, 02_INTEGER: "整数"
- , 02_INTEGER: "整数"
}
}
*/
@@ -260,6 +262,33 @@ RWdNQlpIaTDo5IhJJwIDAQAB
```
+### PEM PKCS#1公钥编码格式
+
+```
+/*****1024位PKCS#1公钥*****/
+-----BEGIN RSA PUBLIC KEY-----
+MIGJAoGBAJjD34zf5ETMO1irAGuz9qz87LwZETk6aeo5XQR+QSIIiOJzNtUQWdne
+pGMtsMBN+YHE1DpzoWBrydfbyCUQf9ov9EbYp2kjwoxSooCzM3J2wdJ6H0xIpx3n
+OBLg24TS755HsIHyQ5aKmIsNCZjfySkzfqlFZ01CWkhpMOjkiEknAgMBAAE=
+-----END RSA PUBLIC KEY-----
+
+/*****二进制表述*****/
+3081890281810098C3DF8CDFE444CC3B58AB006BB3F6ACFCECBC1911393A69EA395D047E41220888E27336D51059D9DEA4632DB0C04DF981C4D43A73A1606BC9D7DBC825107FDA2FF446D8A76923C28C52A280B3337276C1D27A1F4C48A71DE73812E0DB84D2EF9E47B081F243968A988B0D0998DFC929337EA945674D425A486930E8E48849270203010001
+
+
+/*****二进制分解(和PKCS#8公钥格式就是只留了N、E两个数据,及其简单)*****/
+30 81 89
+
+ /*RSA Modulus*/
+ 02 81 81
+ 0098C3DF8CDFE444CC3B58AB006BB3F6ACFCECBC1911393A69EA395D047E41220888E27336D51059D9DEA4632DB0C04DF981C4D43A73A1606BC9D7DBC825107FDA2FF446D8A76923C28C52A280B3337276C1D27A1F4C48A71DE73812E0DB84D2EF9E47B081F243968A988B0D0998DFC929337EA945674D425A486930E8E4884927
+
+ /*RSA Exponent*/
+ 02 03
+ 010001
+```
+
+
### PEM PKCS#1私钥编码格式
```
@@ -398,7 +427,7 @@ openssl genrsa -out private.pem 1024
::提取公钥PKCS#8
openssl rsa -in private.pem -pubout -out public.pem
-::转换成RSAPublicKey PKCS#1?
+::转换成RSAPublicKey PKCS#1
openssl rsa -pubin -in public.pem -RSAPublicKey_out -out public.pem.rsakey
::加密
@@ -407,8 +436,8 @@ echo abcd123 | openssl rsautl -encrypt -inkey public.pem -pubin -out data.enc.bi
::解密
openssl rsautl -decrypt -in data.enc.bin -inkey private.pem -out data.dec.txt
-::测试RSAPublicKey PKCS#1?,不出意外会出错
-::因为这个公钥里面没有OID,通过RSA_PEM转换成PKCS#1自动带上OID就能正常加密
+::测试RSAPublicKey PKCS#1,不出意外会出错
+::因为这个公钥里面没有OID,通过RSA_PEM转换成PKCS#8自动带上OID就能正常加密
echo abcd123 | openssl rsautl -encrypt -inkey public.pem.rsakey -pubin
```
diff --git a/RSA.cs b/RSA.cs
index 242938c..3d5185a 100644
--- a/RSA.cs
+++ b/RSA.cs
@@ -16,18 +16,6 @@ public string ToXML(bool convertToPublic = false) {
return rsa.ToXmlString(!rsa.PublicOnly && !convertToPublic);
}
/// /nSZaBqEGehINeMa805aAqjNOhlHNYGZmF/C4evMvsc=
3/GsDJA/AnKq/lqbpCr1OB5h2wIKsLlPGafPljFzN9s=
+N3qwya7gWN568BuciUwkSlgWVlORusk267Nkkiu3jc=
05o0BiIaDFYtHYNUh5/ROgDSkWqPXjy8Nlmh0S6QdNM=
+
+
+
+
+
+
+[](?)
+
+[](?)
+
+[](?)
+
+[](?)
+
+[](?)
+
+[](?)
+
+# :open_book:Documentation
+
+## Encryption Paddings
+
+> In the table below, Frame is the support of .NET Framework, Core is the support of .NET Core, and BC is the support of the BouncyCastle encryption enhancement library (can be registered through the RSA_Util.UseBouncyCastle method); √ means support, × means no support, and other values are A certain version starts to support; among them, the mask generation function MGF1 of OAEP uses the same Hash algorithm as OAEP.
+
+Padding|Algorithm|Frame|Core|BC
+:-|:-|:-:|:-:|:-:
+NO|RSA/ECB/NoPadding|×|×|√
+PKCS1 |RSA/ECB/PKCS1Padding|√|√|√
+OAEP+SHA1 |RSA/ECB/OAEPwithSHA-1andMGF1Padding|√|√|√
+OAEP+SHA256|RSA/ECB/OAEPwithSHA-256andMGF1Padding|4.6+|√|√
+OAEP+SHA224|RSA/ECB/OAEPwithSHA-224andMGF1Padding|×|×|√
+OAEP+SHA384|RSA/ECB/OAEPwithSHA-384andMGF1Padding|4.6+|√|√
+OAEP+SHA512|RSA/ECB/OAEPwithSHA-512andMGF1Padding|4.6+|√|√
+OAEP+SHA-512/224|RSA/ECB/OAEPwithSHA-512/224andMGF1Padding|×|×|√
+OAEP+SHA-512/256|RSA/ECB/OAEPwithSHA-512/256andMGF1Padding|×|×|√
+OAEP+SHA3-256|RSA/ECB/OAEPwithSHA3-256andMGF1Padding|×|8+|√
+OAEP+SHA3-224|RSA/ECB/OAEPwithSHA3-224andMGF1Padding|×|×|√
+OAEP+SHA3-384|RSA/ECB/OAEPwithSHA3-384andMGF1Padding|×|8+|√
+OAEP+SHA3-512|RSA/ECB/OAEPwithSHA3-512andMGF1Padding|×|8+|√
+OAEP+MD5 |RSA/ECB/OAEPwithMD5andMGF1Padding|4.6+|√|√
+
+
+
+## Signature Paddings
+
+> In the table below, Frame is the support of .NET Framework, Core is the support of .NET Core, and BC is the support of the BouncyCastle encryption enhancement library (can be registered through the RSA_Util.UseBouncyCastle method); √ means support, × means no support, and other values are A certain version starts to support; the number of salt bytes of PSS is equal to the number of bytes of the hash algorithm used, the mask generation function MGF1 of PSS uses the same hash algorithm as that of PSS, and the value of the trailing attribute TrailerField is fixed at 0xBC.
+
+Padding|Algorithm|Frame|Core|BC
+:-|:-|:-:|:-:|:-:
+SHA1 ... SHA3-512|Same as PKCS1+SHA***|||
+PKCS1+SHA1 |SHA1withRSA|√|√|√
+PKCS1+SHA256|SHA256withRSA|√|√|√
+PKCS1+SHA224|SHA224withRSA|×|×|√
+PKCS1+SHA384|SHA384withRSA|√|√|√
+PKCS1+SHA512|SHA512withRSA|√|√|√
+PKCS1+SHA-512/224|SHA512/224withRSA|×|×|√
+PKCS1+SHA-512/256|SHA512/256withRSA|×|×|√
+PKCS1+SHA3-256|SHA3-256withRSA|×|8+|√
+PKCS1+SHA3-224|SHA3-224withRSA|×|×|√
+PKCS1+SHA3-384|SHA3-384withRSA|×|8+|√
+PKCS1+SHA3-512|SHA3-512withRSA|×|8+|√
+PKCS1+MD5 |MD5withRSA|√|√|√
+PSS+SHA1 |SHA1withRSA/PSS|4.6+|√|√
+PSS+SHA256|SHA256withRSA/PSS|4.6+|√|√
+PSS+SHA224|SHA224withRSA/PSS|×|×|√
+PSS+SHA384|SHA384withRSA/PSS|4.6+|√|√
+PSS+SHA512|SHA512withRSA/PSS|4.6+|√|√
+PSS+SHA-512/224|SHA512/224withRSA/PSS|×|×|√
+PSS+SHA-512/256|SHA512/256withRSA/PSS|×|×|√
+PSS+SHA3-256|SHA3-256withRSA/PSS|×|8+|√
+PSS+SHA3-224|SHA3-224withRSA/PSS|×|×|√
+PSS+SHA3-384|SHA3-384withRSA/PSS|×|8+|√
+PSS+SHA3-512|SHA3-512withRSA/PSS|×|8+|√
+PSS+MD5 |MD5withRSA/PSS|4.6+|√|√
+
+
+
+[](?)
+
+[](?)
+
+## RSA_PEM Class Documentation
+The `RSA_PEM.cs` file does not depend on any files, you can directly copy this file to use in your project; through `FromPEM`, `ToPEM` and `FromXML`, `ToXML` two pairs of methods, you can implement PEM `PKCS#1`, `PKCS#8` mutual conversion, PEM, XML mutual conversion.
+
+Note: `openssl rsa -in privateKey -pubout` exports PKCS#8 format public key (used more), `openssl rsa -pubin -in PKCS#8 publicKey -RSAPublicKey_out` exports PKCS#1 format public key (rarely used).
+
+
+### Static Attributes and Methods
+
+`RSA_PEM` **FromPEM(string pem)**: Create RSA with PEM format key, support PKCS#1, PKCS#8 format PEM, error will throw an exception. pem format such as: `-----BEGIN XXX KEY-----....-----END XXX KEY-----`.
+
+`RSA_PEM` **FromXML(string xml)**: Convert the key in XML format to PEM, support public key xml, private key xml, and an exception will be thrown if an error occurs. xml format such as: `
+ ///
null: 等同于PKCS1
+ ///
"": 等同于PKCS1
+ ///
RSA: 等同于PKCS1
+ ///
PKCS: 等同于PKCS1
+ ///
RAW: 等同于NO
+ ///
OAEP: 等同于OAEP+SHA1
+ ///
RSA/ECB/OAEPPadding: 等同于OAEP+SHA1
+ ///
+ ///
NO: RSA/ECB/NoPadding
+ ///
PKCS1: RSA/ECB/PKCS1Padding (默认值,等同于"RSA")
+ ///
OAEP+SHA1 : RSA/ECB/OAEPwithSHA-1andMGF1Padding
+ ///
OAEP+SHA256: RSA/ECB/OAEPwithSHA-256andMGF1Padding
+ ///
OAEP+SHA224: RSA/ECB/OAEPwithSHA-224andMGF1Padding
+ ///
OAEP+SHA384: RSA/ECB/OAEPwithSHA-384andMGF1Padding
+ ///
OAEP+SHA512: RSA/ECB/OAEPwithSHA-512andMGF1Padding
+ ///
OAEP+SHA-512/224: RSA/ECB/OAEPwithSHA-512/224andMGF1Padding (SHA-512/*** 2012年发布)
+ ///
OAEP+SHA-512/256: RSA/ECB/OAEPwithSHA-512/256andMGF1Padding
+ ///
OAEP+SHA3-256: RSA/ECB/OAEPwithSHA3-256andMGF1Padding (SHA3-*** 2015年发布)
+ ///
OAEP+SHA3-224: RSA/ECB/OAEPwithSHA3-224andMGF1Padding
+ ///
OAEP+SHA3-384: RSA/ECB/OAEPwithSHA3-384andMGF1Padding
+ ///
OAEP+SHA3-512: RSA/ECB/OAEPwithSHA3-512andMGF1Padding
+ ///
OAEP+MD5 : RSA/ECB/OAEPwithMD5andMGF1Padding
+ ///
+ ///
如果padding包含RSA字符串,将原样返回此值,用于提供可能支持的任何值
+ ///
非以上取值,将会抛异常
+ ///
+ ///
其中OAEP的掩码生成函数MGF1使用和OAEP相同的Hash算法
+ ///
+ ///
以上填充模式全部可用于BouncyCastle的RSA实现;但如果是使用的.NET自带的RSA实现,将会有部分模式无法支持:不支持全部SHA224、SHA-512/256、SHA-512/224,SHA3需要.NET8以上才支持,.NET Framework 4.5及以下只持OAEP+SHA1不支持其他OAEP
+ ///
+ ///
参考:https://learn.microsoft.com/zh-cn/dotnet/api/system.security.cryptography.rsaencryptionpadding
+ ///
///
+ ///
SHA*** : 等同于PKCS1+SHA***,比如"SHA256" == "PKCS1+SHA256"
+ ///
MD5 : 等同于PKCS1+MD5
+ ///
RSASSA-PSS: 等同于PSS+SHA1
+ ///
+ ///
PKCS1+SHA1 : SHA1withRSA
+ ///
PKCS1+SHA256: SHA256withRSA
+ ///
PKCS1+SHA224: SHA224withRSA
+ ///
PKCS1+SHA384: SHA384withRSA
+ ///
PKCS1+SHA512: SHA512withRSA
+ ///
PKCS1+SHA-512/224: SHA512/224withRSA (SHA-512/*** 2012年发布)
+ ///
PKCS1+SHA-512/256: SHA512/256withRSA
+ ///
PKCS1+SHA3-256: SHA3-256withRSA (SHA3-*** 2015年发布)
+ ///
PKCS1+SHA3-224: SHA3-224withRSA
+ ///
PKCS1+SHA3-384: SHA3-384withRSA
+ ///
PKCS1+SHA3-512: SHA3-512withRSA
+ ///
PKCS1+MD5 : MD5withRSA
+ ///
+ ///
PSS+SHA1 : SHA1withRSA/PSS
+ ///
PSS+SHA256: SHA256withRSA/PSS
+ ///
PSS+SHA224: SHA224withRSA/PSS
+ ///
PSS+SHA384: SHA384withRSA/PSS
+ ///
PSS+SHA512: SHA512withRSA/PSS
+ ///
PSS+SHA-512/224: SHA512/224withRSA/PSS (SHA-512/*** 2012年发布)
+ ///
PSS+SHA-512/256: SHA512/256withRSA/PSS
+ ///
PSS+SHA3-256: SHA3-256withRSA/PSS (SHA3-*** 2015年发布)
+ ///
PSS+SHA3-224: SHA3-224withRSA/PSS
+ ///
PSS+SHA3-384: SHA3-384withRSA/PSS
+ ///
PSS+SHA3-512: SHA3-512withRSA/PSS
+ ///
PSS+MD5 : MD5withRSA/PSS
+ ///
+ ///
如果hash包含RSA字符串,将原样返回此值,用于提供可能支持的任何值
+ ///
非以上取值,将会抛异常
+ ///
+ ///
其中PSS的salt字节数等于使用的Hash算法字节数,PSS的掩码生成函数MGF1使用和PSS相同的Hash算法,跟踪属性TrailerField取值固定为0xBC
+ ///
+ ///
以上填充模式全部可用于BouncyCastle的RSA实现;但如果是使用的.NET自带的RSA实现,将会有部分模式无法支持:不支持全部SHA224、SHA-512/256、SHA-512/224,SHA3需要.NET8以上才支持,.NET Framework 4.5及以下不支持PSS
+ ///
+ ///
参考:https://learn.microsoft.com/zh-cn/dotnet/api/system.security.cryptography.rsasignaturepadding
+ ///
/// K
z&C*SDl5=7zDB0g1!}?bZZx+cwihN$wm@i1*!}v>b(~v2ewH-tniItnE!MTF-iRtvW
z#pVh^JvgPbzybJ5?fja#pS(2lcL(wNt<1sRn4cAa7)%J+`wwd?Bx7OprS>0_jd}iF
zWcb~|a$$pZ$+C+jTSM6O%ftFVdz;(YU;RTb#e4suAABGWTt0E>KV&NfzSGPM
z&F|87cSerZkB)Xn=2w1n_Z%Iqj~wj+za~eHj%tq9YvxxR2RFMW*Wya35X@9u(|TO~
zuybI1&ETG6z?5U$;>h64=!Hfc1B0~3gS)ql0w{~=OC}V}Gm-8wK)8|jhncclH3k-K
zrR18OP#>H>^eWi+J6GJzl^hR8q+=2^w&A3j%C+#1-#QW6Y!6r=`uENI5O)S%z_{P@
zqSE53GJ)`q%(&}UrT&61Bl^8*0MsEo?svZ*E%=XElcK8np-B~C=9l=0*pt|}yK#Iq
zolW??g~da6LUYMkTrc5@Ldl%$&ns@d+82atQT&M`FPTflC@=?WX9?W(jxupiZz-^><;=R~^WokYqUu}K
zd%E-8Jljxx^(fq;pJ>eey=N}N$lWbp2W=}`8i2^oQ<8P$9ul-J6Uc`ZTVy`l`Pvt;
z>S3$-`}9OR!`E}21iW9N507==^;4fG?^$Na7C~1}R0yF`o}BKvURznK%4TI&D^O0t
zx*c5xFz<%@m?FwiHaQnlx2408ePu_TSHis=nj!eU$$7#?fMp_eF?#=EKindloHA=w
zgsCS*g*>Oqkyrfe<5eFY%$V)pMn@s)Zno?
r(F@_#R=p?E&Z;fT(ER;2
zx}_SB7~XFWHW;HYx|&^8p4wi-@+}m<*Fnv}8f7MU{<|sm=$x$3>>gvDDD>Ha)5@^T
zM3=m0b5$O9Qrn#P?p?39uFrit@abS-^RC((hPS%qI#K7uNIL3a`1?swKffB-?mlrR
z?FnnWWxkGlUHaK$w}`J{RGCETCi+01Q2}|-K;}oZFurdhvAHS%fl;9Gj_^h{2k;eV
zsZA{EtvG$W1k2!pJytK7?p#E6CCM*&I>%fWhEJ#2(caAI*>LeIUcVPO-V46dhWYUx
zl}=soaLz)@55Ba&oOE2KP(9!p$gV~__3H$``DSTNqt8^Ku7xWz@@vR$HV6=Wq#|rP
zs65iI092IIuTnhj@a?|wdG|eadE
j
zj();uMY2ED*VjysZz~$rpBjQJD%FhU*?Zo(oV+$5b02dJeC>FVr{;!nt}&JT7rK*E
z+EP_F67$@peX+6#f6LK`nD#R%)t=EXp2Z$L@OrHCPm|KbnA5ZRg>dGQRwX#e;C1c&
zLQZqgXwW67u90np%E*zB_Ss{BOpE4z^XONTFaotCPU;v
B6JV5G)>g24bXGJCBvRtsO){Yfgj8_Y=|V+X?gQi$g)3$TcmtY?hGb
z$E7{gC(Goetrx5=k(QJ+rILHe)AJXh5$Wq3F>Ohbu>Z7#Y#F}SlG2oX8m(xiA
_sBWP(zcu=@rpfCryZg2ZL>*`BQD!xDuq=}#d+8#5
zx@ja0JJDLx?yfXnR#+K>)*X$1yfp`#{l|7W`6BBkblyQHds2>NS~w#cu)-p>Y~S6j
z329fiRvUPED)rR{J?!fQs&mdVE^*fvxdBX9EV_T!mzPz@;TW;cf%v~e&&S7qe>pxp
z6zU45@6G-=zPTmzp3;5H-KKxq4|kt31xIB>&`ka2KB1TMe@>(_6F%+#aPl1~(L80C
zyC7aVl1s#G?i0u1%h~e$^{-;>tf5T13FAKxbxqWW*$?5@7f!&rx3BMHsDD?(T6;~x
zJ=dq4YKtTAbwm1A9&rHfyW?ue-*1n7Pn2p;23A`iyX-j$XIygtet6;zST&U}_o=IJ
z4KBuIBT|2JOx`7CP&9w|