I am using the commoncrypto
library on the iPhone to create a pair of RSA keys and I am trying to send the public key to a server (Python) so that I can use it to verify a signature sent from the phone.
I'm using the exact code from the CommonCrypto example using the method getPublicKeyBits()
which looks like this:
`- (NSData )getPublicKeyBits { OSStatus sanityCheck = noErr; NSData publicKeyBits = nil; NSData* publicTag = [[NSData alloc] initWithBytes:publicKeyIdentifier length:sizeof(publicKeyIdentifier)]; CFDataRef cfresult = NULL;
NSMutableDictionary * queryPublicKey = [[NSMutableDictionary alloc] init];
// Set the public key query dictionary.
[queryPublicKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
[queryPublicKey setObject:publicTag forKey:(__bridge id)kSecAttrApplicationTag];
[queryPublicKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
[queryPublicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnData];
// Get the key bits.
sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)queryPublicKey, (CFTypeRef*)&cfresult);
if (sanityCheck != noErr)
{
publicKeyBits = nil;
}
else
{
publicKeyBits = (__bridge_transfer NSData *)cfresult;
}
return publicKeyBits;
}`
The problem is that I don't know how, exactly, the key is being stored or how to pass it. I am using the getPublicKeyBits()
to get it in a NSData
structure, and I've imported a library to encode it in base64
. I'm getting a key (SHA1, I'd like to move to SHA256, but that's secondary to getting this working) and the base64
version looks like other keys I've found here and in other people solving RSA problems.
I've been trying to use the M2Crypto
library in Python and when I try to verify I'm getting the error "RSA Error: No Start Line"
. Here's the code I'm using to receive the public key:
pubKey = request.form['publickey']
uid = uuid4().hex
while not unique(uid, User):
uid = uuid.uuid4().hex
user = User(uid, email, secret, pubKey)
And the code I'm using to check the signature:
def validate(sessionKey, sig, pem):
bio = BIO.MemoryBuffer(pem.encode('ascii'))
rsa = RSA.load_pub_key_bio(bio)
pubkey = EVP.PKey()
pubkey.assign_rsa(rsa)
pubkey.reset_context(md='sha1')
pubkey.verify_init()
pubkey.verify_update(sessionKey)
return pubkey.verify_final(sig)
I'm really stumped as to what I'm doing wrong but I feel like I'm getting close. If my whole method is not the way you'd do it, I'd love to hear any other way to generate RSA keys on the phone, publish the public key to a server, and then verify a signature from the phone on that server.
Thanks!