如何将在Android上创建的RSA公钥成功导入C#.net



我正在开发一款Xamarin移动应用程序,该应用程序使用iOS和Android的公钥/私钥加密、签名和验证。在iOS和Android上创建的公钥将被发送到.net服务端点,该服务将在该服务端点尝试导入公钥以验证签名。

在Xamarin.iOS中,我正在创建如下的公钥

public async Task<string> CreateRandomKeyPair()
{
using (var access = new SecAccessControl(SecAccessible.WhenUnlockedThisDeviceOnly, SecAccessControlCreateFlags.BiometryAny))
{
var keyParameters = new SecKeyGenerationParameters
{
KeyType = SecKeyType.RSA,
KeySizeInBits = 2048,
Label = AppInfo.PackageName,
TokenID = SecTokenID.None,
PrivateKeyAttrs = new SecKeyParameters
{
IsPermanent = true,
ApplicationTag = NSData.FromString(AppInfo.PackageName, NSStringEncoding.UTF8),
AccessControl = access,
CanSign = true,
CanVerify = true
}
};
var privateKey = SecKey.CreateRandomKey(keyParameters.Dictionary, out NSError nsError);
var publicKey = privateKey.GetPublicKey();
NSData keyData = publicKey.GetExternalRepresentation();
var publicKeyString = keyData.GetBase64EncodedString(NSDataBase64EncodingOptions.None);
return publicKeyString;
}

在Xamarin.Android中,我正在创建如下的公钥

public async Task<string> CreateRandomKeyPair()
{
KeyPairGenerator _keyPairGenerator = KeyPairGenerator.GetInstance(KeyProperties.KeyAlgorithmRsa, "AndroidKeyStore");
_keyPairGenerator.Initialize(new KeyGenParameterSpec.Builder("MyKeys", KeyStorePurpose.Sign | KeyStorePurpose.Verify)
.SetDigests(KeyProperties.DigestSha256)
.SetUserAuthenticationRequired(true)
.SetSignaturePaddings(KeyProperties.SignaturePaddingRsaPkcs1)
.SetKeySize(2048).Build());
KeyPair keyPair = _keyPairGenerator.GenerateKeyPair();
IPublicKey publicKey = keyPair.Public;
byte[] publicKeyBytes = publicKey.GetEncoded();
string publicKeyString = Base64.EncodeToString(publicKeyBytes, Base64Flags.NoWrap);
return publicKeyString;
}

在一个C#.net控制台应用程序中,我试图导入如下所示的公钥

using System;
using System.Security.Cryptography;
namespace AndroidPubkey
{
class Program
{
static void Main(string[] args)
{
try
{
var rsa = RSA.Create(2048);
//Android generated public key
byte[] pubKey = Convert.FromBase64String("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwgF3bLq/hnNHi3sQoB5C/xusj23ruksW74fCwHMNXxJpsghfqMbhu1E8p2NwxjSkXzDW+QI7DYc8aX9FJruKnvDGswaYdK7vvd4GZmxmYUNPRK6i8cNq/o9mwsAVpv4MmjImY0fSZLjAxW0SXhAZ6iFclOlWkyFo5DmvovBiF4i3CrWpdyHYoVEujRQJ7Rq0q9JuE2lCSNDTIPQYxC9Slw18r5PYjgIgHYmDJvkNlr7wGDl3vlbtHPpUUmRJXCMiuXW7RCp8vasA/2f12MpyTzgSCj/gGb4sPUVvYNQ1n4hU6r3kyz22EW3ZUy5RPPjRn5Hu2CXHMHOeJaB3ZkBoTwIDAQAB");
//iOS generated public key
//byte[] pubKey = Convert.FromBase64String("MIIBCgKCAQEAttcTCPsrCic/jC2PGYQUZ41JVn0SD54ZMj01zq5ik72mq1UsQKVb2pwj2lk4ZkZ+nCWU9qk2DddQ9jemE5lWlBVgzh0udyLXpVKESq3YP6DAWcFb45rERryEuYm6steQ5voo62grwLyi8uYTNRuSlUCGfKd/x3tcHm6Mx46P4zSoKv2ykpW6MTgbaTm6D/6/NNA7Qis5+4B/g2eAWJT/rZh6VRf895EQhMvRA1dtCaHqmv95tSJjaiIlRohO4WYJ8bBWfI1z66pMCWFvig5D7Git+pv/A8xCyupBxhkiJDfKS42npuhAcaRbt/QIKUiDWssrlwKyqcNfJghHY12BBwIDAQAB");
rsa.ImportRSAPublicKey(pubKey, out int bytes);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}

Xamarin.iOS上生成的公钥成功地将导入C#.net并且我能够执行签名验证时,Xamarin.Android上生成的私钥未能将导入C#.net并且给我异常消息,";导入中存在未知格式"具有低于堆叠通道

在Interop.AppleCrypto.ImportEphemeralKey(ReadOnlyPan 1 keyBlob,Boolean hasPrivateKey(位于System.Security.Cryptography.RSAIimplementation.RSASecurityTransforms.ImportSubjectPublicKeyInfo(ReadOnlySpan 1源,Int32&bytesRead(位于System.Security.Cryptography.RSAIimplementation.RSASecurityTransforms.ImportRSAPublicKey(ReadOnlySpan 1源,Int32&bytesRead(在/Users/developer/Projects/AndroidPubkey/AndroidPubkey/Program.cs:line 17 中的AndroidPubkey.Program.Main(String[]args(

注意:我正在Mac操作系统上运行控制台应用程序。我看到在Android上创建的公钥字符串比在iOS上创建的长。

请帮助我理解此处的问题,并创建跨平台兼容的RSA密钥。

根据@Topaco的评论建议,我可以修复如下问题。我在这里回答是为了让其他寻求答案的人从中受益。我添加了一个条件,即android的公钥字节数组长度为294,否则它将作为iOS生成的公钥导入。

using System;
using System.Security.Cryptography;
namespace AndroidPubkey
{
class Program
{
static void Main(string[] args)
{
try
{
var rsa = RSA.Create(2048);
//Android generate public key
byte[] pubKey = Convert.FromBase64String("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgov1p4sCDlCxRaGq4Am3sDOffwtP4iVdmIzXDqELyA251UBBAbZeyC/wCrVllkNAS644nFHDbkPko2EZWIMY0Rl9t/x37GV2gAnJjQ8HLR/WnxqsHiD83qczCqkHwr/AiT4bdAJyiFMwWn20fXfiiksxP0dtmvzYFz0igONj1/PRuzVnblTDIvgP5Okq1EvKC1UjRV8QDTPqzxFbTzi1YAsL02n1zEsnYH3+96syPHi9TE9r9/vk1h/M+q3p+gS0nwpz5Dz7+DQAvOYMkCsNU/IjU6GZwQNwMfh2s59UuYFppckj9gI8LGlBq2QVCAZj9U9LEGawj4BggOGmiRPXFQIDAQAB");
//iOS generated public key
//byte[] pubKey = Convert.FromBase64String("MIIBCgKCAQEAttcTCPsrCic/jC2PGYQUZ41JVn0SD54ZMj01zq5ik72mq1UsQKVb2pwj2lk4ZkZ+nCWU9qk2DddQ9jemE5lWlBVgzh0udyLXpVKESq3YP6DAWcFb45rERryEuYm6steQ5voo62grwLyi8uYTNRuSlUCGfKd/x3tcHm6Mx46P4zSoKv2ykpW6MTgbaTm6D/6/NNA7Qis5+4B/g2eAWJT/rZh6VRf895EQhMvRA1dtCaHqmv95tSJjaiIlRohO4WYJ8bBWfI1z66pMCWFvig5D7Git+pv/A8xCyupBxhkiJDfKS42npuhAcaRbt/QIKUiDWssrlwKyqcNfJghHY12BBwIDAQAB");
if (pubKey.Length == 294)
{
rsa.ImportSubjectPublicKeyInfo(pubKey, out int bytes);
}
else
{
rsa.ImportRSAPublicKey(pubKey, out int bytes);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}

最新更新