Having trouble to get a very basic version of SecKeySign() to work (I.e. porting a working OSX SecSignTransformCreate()/SecTransformSetAttribute()/SecTransformExecute() to iOS):
The code is pretty much as per http://developer.apple.com/library/ios/#samplecode/CryptoExercise/Listings/Classes_SecKeyWrapper_m.html – albeit even further simplified.
First up – setting things up – as per above link. No changes.
const char someData[] = "No one loves pain itself, but those who seek...";
NSData * blob = [NSData dataWithBytes:someData length:sizeof(someData)];
assert(blob);
SecKeyRef publicKeyRef, privateKeyRef;
int keySize = 2048;
OSStatus sanityCheck = noErr;
NSMutableDictionary * privateKeyAttr = [[NSMutableDictionary alloc] init];
NSMutableDictionary * publicKeyAttr = [[NSMutableDictionary alloc] init];
NSMutableDictionary * keyPairAttr = [[NSMutableDictionary alloc] init];
// attribute dictionaries for 2048 bit RSA key pair.
//
[keyPairAttr setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
[keyPairAttr setObject:[NSNumber numberWithUnsignedInteger:keySize] forKey:(__bridge id)kSecAttrKeySizeInBits];
[privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent];
[publicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent];
[keyPairAttr setObject:privateKeyAttr forKey:(__bridge id)kSecPrivateKeyAttrs];
[keyPairAttr setObject:publicKeyAttr forKey:(__bridge id)kSecPublicKeyAttrs];
And the actual work starts with generating a keypair:
sanityCheck = SecKeyGeneratePair((__bridge CFDictionaryRef)keyPairAttr, &publicKeyRef, &privateKeyRef);
assert(sanityCheck == noErr);
NSLog(@"Pub/Priv: %@/%@", publicKeyRef, privateKeyRef);
which works splendidly insofar as I can see.
The trouble is with using them to sign; or rather the signing:
// Zero-ed Buffer for the signature.
//
size_t signatureBytesSize = SecKeyGetBlockSize(privateKeyRef);
assert(signatureBytesSize == keySize / 8);
uint8_t * signatureBytes = malloc( signatureBytesSize * sizeof(uint8_t) );
memset((void *)signatureBytes, 0x0, signatureBytesSize);
// Sign the binary blob; with type 1 padding.
//
sanityCheck = SecKeyRawSign(privateKeyRef,
kSecPaddingPKCS1,
(const uint8_t *)[blob bytes], [blob length],
(uint8_t *)signatureBytes, &signatureBytesSize
);
assert(sanityCheck == noErr);
which always returns a -50/errSecParam (One or more parameters passed to a function were not valid.).
Any suggestions ? This is on an actual iPhone ?
Thanks,
Dw.
Insofar as I can work out – the only acceptable inputs for SecKeyRawSign() are a data block of SHA_DIGEST_LEN. Anything else is rejected.
The SHA1 hash is calculated by this function – so one only needs to pass the needed space.
I’ve not yet found a way to specify a SHA2 or other hash.
Dw