I'm developing a Xamarin mobile app that uses public/private key encryption, signing and verifying for both iOS and Android. The public key created on iOS and Android is being sent to a .net service endpoint where the service tries to import the public key to verify the signatures.
In Xamarin.iOS I'm creating the public key as below
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;
}
In Xamarin.Android, I'm creating the public key as below
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;
}
In a C#.net console app, I'm trying to import the public key as below
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);
}
}
}
}
while the public key generated on Xamarin.iOS is successfully importing into C#.net and I'm able to perform verifying a signature, the public key generated on Xamarin.Android is failing to import in C#.net and giving me the exception message, "Unknown format in import." with below stacktrace
at Interop.AppleCrypto.ImportEphemeralKey(ReadOnlySpan 1 keyBlob, Boolean hasPrivateKey) at System.Security.Cryptography.RSAImplementation.RSASecurityTransforms.ImportSubjectPublicKeyInfo(ReadOnlySpan 1 source, Int32& bytesRead) at System.Security.Cryptography.RSAImplementation.RSASecurityTransforms.ImportRSAPublicKey(ReadOnlySpan 1 source, Int32& bytesRead) at AndroidPubkey.Program.Main(String[] args) in /Users/developer/Projects/AndroidPubkey/AndroidPubkey/Program.cs:line 17
Note: I'm running the console app on Mac OS. I see that the public key string created on Android is longer than the one created on iOS.
Please help me in understanding the issue here and also creating RSA keys that are cross-platform compatible.