How to store RSA key-pair on iOS keychain?

Hi,
I'm developing a Xamarin Forms app, and in iOS I want to create a RSA key-pair and be able to store the key-pair in the iOS KeyChain and retrieve the publicKey from iOS KeyChain anytime i want to. However i'm facing some problems due to the lack of documentation available on the internet about this issue.
So i created my RSA key pair this way, since i have to send the public key in DER format to a server (using BouncyCastle).
`

        RsaKeyPairGenerator generator = new RsaKeyPairGenerator();

        generator.Init(new KeyGenerationParameters(new SecureRandom(), 2048));

        AsymmetricCipherKeyPair keyPair = generator.GenerateKeyPair();

        RsaKeyParameters keyParam = (RsaKeyParameters)keyPair.Public;

        var info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyParam);

        byte[] RsaBytes = info.GetEncoded();

`

and then i need to store the keys on KeyChain but i can't find anything that helps me so i tried this way (byte[] value = RsaBytes):

`        private void StoreKeysInKeychain(string key, byte[] value)
        {
        SecRecord record = new SecRecord(SecKind.GenericPassword)
                    {
                        ValueData = NSData.FromArray(value),
                        Generic = NSData.FromString(key)
                    };
        record.AccessControl = new SecAccessControl(SecAccessible.WhenUnlocked, SecAccessControlCreateFlags.TouchIDAny);
        SecStatusCode  err = SecKeyChain.Add(record);
    }`

First, i don't know if this is the best way to store anything is iOS KeyChain.
Second, when i get the 'ValueData' from KeyChain, i can't convert it back to a byte[] so i can't get my publicKey again anymore.
I get the key using the following method

         NSData GetRecordsFromKeychain(string key)
                {
                    SecStatusCode res;
                    var rec = new SecRecord(SecKind.GenericPassword)
                    {
                        Generic = NSData.FromString(key)
                    };

                    SecRecord match = SecKeyChain.QueryAsRecord(rec, out res);
                    if (match != null)
                    {
                        // nsdata object :  match.ValueData;
                        return match.ValueData;
                    }
                    return null;
                }

and i try to convert it back to a byte[] that represents my public key using the following methods:

    byte[] marshalBytes = new byte[nsdata.Length];
    System.Runtime.InteropServices.Marshal.Copy(nsdata.Bytes, marshalBytes, 0, Convert.ToInt32(nsdata.Length));
    byte[] storedBytes = ToByte(nsdata);
    byte[] convertedBytes = nsdata.ToArray();

No one of them is the same as RsaBytes:

    bool result1 = RsaBytes.SequenceEqual(storedBytes);         // FALSE
    bool result2 = RsaBytes.SequenceEqual(convertedBytes);  // FALSE
    bool result3 = storedBytes.SequenceEqual(convertedBytes); // TRUE
    bool result4 = marshalBytes.SequenceEqual(RsaBytes);    // FALSE
    bool result5 = marshalBytes.SequenceEqual(storedBytes);     // TRUE

So, summing up all the problems
1 - I don't know the best way to create an RSA key pair in iOS and get publicKey DER-encoded (so I used BouncyCastle)
2 - Don't know how to store it properly on KeyChain
3 - I can access the information i stored, however it's useless since I can't convert it back to a publicKey
4 - When trying to access the information the user should be prompt to use TouchID, always.

I can't find samples of this in the internet... I would really appreciate some help.
Many thanks to everyone.

Sign In or Register to comment.