如何使用 RSA 密钥对 iOS 上的一些数据进行签名和验证(最好使用系统自带的libcommonCrypto
)?
问问题
13716 次
2 回答
31
由于在 StackOverflow 和 Apple 文档上几乎没有任何关于签名和验证的知识,我不得不手动浏览 iOS 头文件并SecKeyRawSign
找到SecKeyRawVerify
. 以下代码行似乎有效。
签署 NSData(使用 SHA256 和 RSA):
NSData* PKCSSignBytesSHA256withRSA(NSData* plainData, SecKeyRef privateKey)
{
size_t signedHashBytesSize = SecKeyGetBlockSize(privateKey);
uint8_t* signedHashBytes = malloc(signedHashBytesSize);
memset(signedHashBytes, 0x0, signedHashBytesSize);
size_t hashBytesSize = CC_SHA256_DIGEST_LENGTH;
uint8_t* hashBytes = malloc(hashBytesSize);
if (!CC_SHA256([plainData bytes], (CC_LONG)[plainData length], hashBytes)) {
return nil;
}
SecKeyRawSign(privateKey,
kSecPaddingPKCS1SHA256,
hashBytes,
hashBytesSize,
signedHashBytes,
&signedHashBytesSize);
NSData* signedHash = [NSData dataWithBytes:signedHashBytes
length:(NSUInteger)signedHashBytesSize];
if (hashBytes)
free(hashBytes);
if (signedHashBytes)
free(signedHashBytes);
return signedHash;
}
验证(使用带有 RSA 的 SHA256):
BOOL PKCSVerifyBytesSHA256withRSA(NSData* plainData, NSData* signature, SecKeyRef publicKey)
{
size_t signedHashBytesSize = SecKeyGetBlockSize(publicKey);
const void* signedHashBytes = [signature bytes];
size_t hashBytesSize = CC_SHA256_DIGEST_LENGTH;
uint8_t* hashBytes = malloc(hashBytesSize);
if (!CC_SHA256([plainData bytes], (CC_LONG)[plainData length], hashBytes)) {
return nil;
}
OSStatus status = SecKeyRawVerify(publicKey,
kSecPaddingPKCS1SHA256,
hashBytes,
hashBytesSize,
signedHashBytes,
signedHashBytesSize);
return status == errSecSuccess;
}
替代方案(OpenSSL):
有一个非常好的替代方案,它直接利用 OpenSSL 而不是 libCommonCrypto。MIHCrypto是一个精心设计的用于 OpenSSL 的 Objective-C 包装库,它使密码学的工作变得非常容易。请参见下面的示例。
生成密钥就是这么简单:
MIHAESKeyFactory *factory = [[MIHAESKeyFactory alloc] init];
id<MIHSymmetricKey> aesKey = [factory generateKey];
或从文件中加载密钥:
NSData *privateKeyData = [[NSFileManager defaultManager] contentsAtPath:"mykey.pem"];
MIHRSAPrivateKey *privateKey = [[MIHRSAPrivateKey alloc] initWithData:privateKeyData];
现在签署一些东西:
NSError *signingError = nil;
NSData *message = // load something to sign from somewhere
NSData *signature = [privateKey signWithSHA256:message error:&signingError]
有关更多示例,请浏览MIHCrypto页面。
于 2014-02-17T10:37:16.430 回答
2
它实际上要简单得多,无需手动创建哈希
func validateRSASignature(signedData: Data, signature: Data, publicKeyData: Data) -> Bool {
// Create a SecKey instance from the public key data.
let publicKey: SecKey! = SecKeyCreateWithData(publicKeyData as NSData, [
kSecAttrKeyType: kSecAttrKeyTypeRSA,
kSecAttrKeyClass: kSecAttrKeyClassPublic
] as NSDictionary, nil)
// Verify the RSA signature.
return SecKeyVerifySignature(publicKey,
.rsaSignatureMessagePKCS1v15SHA512,
signedData as NSData,
signature as NSData,
nil)
}
从 iOS 10 开始这应该是可能的。如果您的关键数据和其他输入发生变化,您可能希望扩展错误处理。
于 2021-01-09T09:45:38.793 回答