我正在使用 Apple 的 Security Framework .我能够在 OS X 上签名并成功验证所有内容,但是当我尝试在 iOS 上使用 SecKeyRawVerify
时,它失败并出现 -9809 错误。
我尝试过各种 PKCS 填充选项和许多其他属性,但我无法正确验证它。
请注意,下面的代码可能到处都是漏洞,只是先尝试让它正常运行。
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;
}
和iOS验证码:
+ (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 命令通过命令行创建了私钥和公钥:
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
格式的公钥是正确的:)
关于ios - 在 OS X 上登录,在 iOS 和 OSStatus 上验证 -9809,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31036959/