loginOS X,在iOS和OSStatus -9809上进行validation
我正在使用苹果的安全框架 。 我能够签署,然后成功validation所有在OS X上,但是当我尝试在iOS上使用SecKeyRawVerify
它失败-9809错误。
我已经玩过各种PKCS填充选项和许多其他属性,但我只是无法得到这个来validation正确。
请注意,下面的代码可能已经泄漏到各地,只是试图让这个function正常第一。
OS X签署代码:
NSData* signData(NSData* plainData, SecKeyRef privateKey) { CFErrorRef error; /* Create the transform objects */ SecTransformRef signer = SecSignTransformCreate(privateKey, &error); if (error) { CFShow(error); exit(-1); } /* Explicitly set padding type (necessary?) */ SecTransformSetAttribute(signer, kSecPaddingKey, kSecPaddingPKCS1Key, &error); if (error) { CFShow(error); exit(-1); } /* Specify digest type */ SecTransformSetAttribute(signer, kSecDigestTypeAttribute, kSecDigestSHA1, &error); if (error) { CFShow(error); exit(-1); } /* OS X calculates SHA1 hash/signature for us */ SecTransformSetAttribute(signer, kSecTransformInputAttributeName, plainData, &error); if (error) { CFShow(error); exit(-1); } CFTypeRef signature = SecTransformExecute(signer, &error); if (error || !signature) { CFShow(error); exit(-1); } CFRelease(signer); return signature; }
和iOSvalidation码:
+ (NSData *)verifyData:(NSData *)data usingKey:(SecKeyRef)publicKey { size_t signatureByteLength = SecKeyGetBlockSize(publicKey); if (signatureByteLength > data.length) { NSLog(@"Signature length is greater that data length."); return nil; } NSData *signature = [data subdataWithRange:NSMakeRange(0, signatureByteLength)]; NSData *plainData = [data subdataWithRange:NSMakeRange(signatureByteLength, data.length - signatureByteLength)]; NSLog(@"signatureLength='%lu', signatureBytes='%@', plainDataLength=%lu", (unsigned long)signature.length, signature, (unsigned long)plainData.length); size_t hashByteLength = CC_SHA1_DIGEST_LENGTH; uint8_t* hashBytes = (uint8_t *)malloc(hashByteLength); if (CC_SHA1([plainData bytes], (CC_LONG)[plainData length], hashBytes)) { NSData *b = [NSData dataWithBytes:hashBytes length:hashByteLength]; NSLog(@"hashBytesLength='%lu', hashBytes=%@", (unsigned long)b.length, b); OSStatus status = SecKeyRawVerify(publicKey, kSecPaddingPKCS1SHA1, // I have also tried kSecPaddingPKCS1, doesn't work hashBytes, hashByteLength, (uint8_t *)[signature bytes], signatureByteLength); switch (status) { case errSecSuccess: NSLog(@"SecKeyRawVerify success."); return plainData; case errSSLCrypto: NSLog(@"SecKeyRawVerify failed: underlying cryptographic error"); break; case errSecParam: NSLog(@"SecKeyRawVerify failed: one or more parameters passed to a function where not valid."); break; default: NSLog(@"SecKeyRawVerify failed: error code '%d'", (int)status); break; } } return nil; }
我使用下面的OpenSSL命令通过命令行创build了私钥和公钥:
1. // Generate private and public key pair openssl genrsa -out rsaPrivate.pem 1024 1a. // Generate public key openssl rsa -in rsaPrivate.pem -pubout -outform PEM -out rsaPublic.pem 2. //Create a certificate signing request with the private key openssl req -new -key rsaPrivate.pem -out rsaCertReq.csr 3. //Create a self-signed certificate with the private key and signing request openssl x509 -req -days 3650 -in rsaCertReq.csr -signkey rsaPrivate.pem -out rsaCert.crt 4. //Convert the certificate to DER format: the certificate contains the public key openssl x509 -outform der -in rsaCert.crt -out rsaCert.der
任何帮助是极大的赞赏。
我想出了这个问题。 我发布的代码是正确的,但是需要根据SecKey.h
头文件将填充设置为kSecPaddingPKCS1SHA1
:
If you are verifying a proper PKCS1-style signature, with DER encoding of the digest type - and the signedData is a SHA1 digest - use kSecPaddingPKCS1SHA1.
另外,你可能要确保你的.der
格式的公钥是正确的:)
if (CC_SHA1([plainData bytes], (CC_LONG)[plainData length], hashBytes)) { NSData *b = [NSData dataWithBytes:hashBytes length:hashByteLength]; NSLog(@"hashBytesLength='%lu', hashBytes=%@", (unsigned long)b.length, b); ... }
看起来你没有正确编码和应用填充。 编码和填充在散列之前得到应用。 请参阅RFC 3447 公钥encryption标准(PKCS)#1:RSAencryption规范版本2.1 (或PKCS#1规范)。