我是新来的验证和证书等。 我面临一个问题,我需要在c#上签一条消息然后验证java上的签名,我面临的问题是我无法使用生成的Base64字符串在(PublicKey)对象上加载Java上的公钥c#,我使用以下代码在c#side
上生成私钥和公钥 CspParameters cspParams = new CspParameters { ProviderType = 1 };
cspParams.KeyContainerName = "MyKeyContainer";
RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(1024);
string publicKey = Convert.ToBase64String(rsaProvider.ExportCspBlob(false));
string privateKey = Convert.ToBase64String(rsaProvider.ExportCspBlob(true));
System.Diagnostics.Debug.WriteLine("pub:" + publicKey);
System.Diagnostics.Debug.WriteLine("pri:" + privateKey);
Console.WriteLine("Key added to container: \n {0}", rsaProvider.ToXmlString(true));
然后我使用以下代码在Java端创建公钥:
X509EncodedKeySpec specc = new X509EncodedKeySpec(org.apache.commons.codec.binary.Base64.decodeBase64("BgIAAACkAABSU0ExAAQAAA......"));
KeyFactory xx = KeyFactory .getInstance("RSA");
PublicKey ssx= xx.generatePublic(specc);
请注意,我从c#控制台复制了base64公钥字符串。 当我尝试在java端运行代码时,我得到以下异常:
java.security.spec.InvalidKeySpecException: Inappropriate key specification: invalid key format
at sun.security.provider.DSAKeyFactory.engineGeneratePublic(Unknown Source)
at java.security.KeyFactory.generatePublic(Unknown Source)
我需要找到一种方法来生成c#上的私钥和公钥(并生成公钥的.cer文件)以在java端加载它,或者找到一种方法将base64公钥字符串加载到( java方面的Publickey)对象。请帮忙!
答案 0 :(得分:0)
从.NET传输公共RSA密钥的最简单方法是检查公共指数值是否为{ 01 00 01 }
,然后发送模数值。在接收方,你接受模数并断言公共指数。
RSAParameters keyParams = rsa.ExportParameters(false);
if (!keyParams.Exponent.SequenceEqual(new byte[] { 0x01, 0x00, 0x01 }))
throw new InvalidOperationException();
Send(keyParams.Modulus);
然后Creating RSA keys from known parameters in Java表示你可以直接在Java端恢复它。
您的下一个选择是继续使用CSP blob,但是用Java编写解析器。数据是使用PUBLICKEYBLOB
调用CryptExportKey
的结果,按https://msdn.microsoft.com/en-us/library/ee442238.aspx和https://msdn.microsoft.com/en-us/library/windows/desktop/aa375601(v=vs.85).aspx#pub_BLOB所述进行数据布局。
总结:
标题(您可以决定跳过,或者仅测试它等于您期望的固定值):
0x06
(PUBLICKEYBLOB
)0x02
(blob v2)0x0000
(保留)0x0000A400
或0x00002400
)0x31415352
毕竟有相关数据:
0x00000400
,又名{ 00 04 00 00 }
(LE)。0x00010001
(又名{ 01 00 01 00 }
),但是因为它在那里你应该尊重它。bitLen/8
个字节表示模数值。因为这是公钥,应该是#34;这个数组中的其余字节"。 .NET Framework没有内置此功能(截至当前版本,4.7)。你可以P / Invoke到CertCreateSelfSignCertificate
,但这会涉及很多变化(因为RSACryptoServiceProvider不会让你获得关键句柄,所以你必须P / Invoke全部那也是。)
你可以" bit bang"自己出DER编码证书。虽然很有趣,但这很难做到,而且可能不是一条可行的道路。
如果您可以迁移到.NET Core,则可以通过CertificateRequest类将创建证书的功能添加到.NET Core 2.0中。对于来自密钥的非常简单的证书:
var certReq = new CertificateRequest(
"CN=SubjectCN",
rsaProvider,
HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1);
// add any extensions you want. I'm not adding any because I said "simple".
DateTimeOffset now = DateTimeOffset.UtcNow;
X509Certificate2 cert = certReq.CreateSelfSigned(now, now.AddMinutes(90));
byte[] xfer = cert.RawData;