iOS pfx SHA1WithRSA 加签,验签

最近搞的一个加签验签,证书文件给的pfx,以前没搞过pfx,大致查了下pfx加密标准是PKCS#12里面包含公钥,以及私钥。这里我们要用到私钥加签,公钥验签,由于iOS这方面资料可能不太多,记录一下,贴下代码

提取私钥,然后进行加签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
-(NSString *)signTheDataSHA1WithRSA:(NSString *)plainText
{
uint8_t* signedBytes = NULL;
size_t signedBytesSize = 0;
OSStatus sanityCheck = noErr;
NSData* signedHash = nil;

NSString * path = [[NSBundle mainBundle]pathForResource:@"Xpay" ofType:@"pfx"];
NSData * data = [NSData dataWithContentsOfFile:path];
//因为pfx之前设置的有密码所以这里要设置一下
NSMutableDictionary * options = [[NSMutableDictionary alloc] init]; // Set the private key query dictionary.
[options setObject:@"xxxx" forKey:(id)kSecImportExportPassphrase];
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
OSStatus securityError = SecPKCS12Import((CFDataRef) data, (CFDictionaryRef)options, &items);
if (securityError!=noErr) {
return nil ;
}
CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
SecIdentityRef identityApp =(SecIdentityRef)CFDictionaryGetValue(identityDict,kSecImportItemIdentity);
SecKeyRef privateKeyRef=nil;
SecIdentityCopyPrivateKey(identityApp, &privateKeyRef);
signedBytesSize = SecKeyGetBlockSize(privateKeyRef);

NSData *plainTextBytes = [plainText dataUsingEncoding:NSUTF8StringEncoding];

signedBytes = malloc( signedBytesSize * sizeof(uint8_t) ); // Malloc a buffer to hold signature.
memset((void *)signedBytes, 0x0, signedBytesSize);

sanityCheck = SecKeyRawSign(privateKeyRef,
kSecPaddingPKCS1SHA1,
(const uint8_t *)[[self getHashBytes:plainTextBytes] bytes],
CC_SHA1_DIGEST_LENGTH,
(uint8_t *)signedBytes,
&signedBytesSize);

if (sanityCheck == noErr)
{
signedHash = [NSData dataWithBytes:(const void *)signedBytes length:(NSUInteger)signedBytesSize];
}
else
{
return nil;
}

if (signedBytes)
{
free(signedBytes);
}
NSString *signatureResult=[NSString stringWithFormat:@"%@",[signedHash base64EncodedString]];

return signatureResult;
}

- (NSData *)getHashBytes:(NSData *)plainText {
CC_SHA1_CTX ctx;
uint8_t * hashBytes = NULL;
NSData * hash = nil;

// Malloc a buffer to hold hash.
hashBytes = malloc( CC_SHA1_DIGEST_LENGTH * sizeof(uint8_t) );
memset((void *)hashBytes, 0x0, kChosenDigestLength);
// Initialize the context.
CC_SHA1_Init(&ctx);
// Perform the hash.
CC_SHA1_Update(&ctx, (void *)[plainText bytes], [plainText length]);
// Finalize the output.
CC_SHA1_Final(hashBytes, &ctx);

// Build up the SHA1 blob.
hash = [NSData dataWithBytes:(const void *)hashBytes length:(NSUInteger)kChosenDigestLength];
if (hashBytes) free(hashBytes);

return hash;
}

提取公钥,验证签名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
BOOL PKCSVerifyBytesSHA1withRSA(NSData* plainData, NSData* signature, SecKeyRef publicKey)
{
size_t signedHashBytesSize = SecKeyGetBlockSize(publicKey);
const void* signedHashBytes = [signature bytes];

size_t hashBytesSize = CC_SHA1_DIGEST_LENGTH;
uint8_t* hashBytes = malloc(hashBytesSize);
if (!CC_SHA1([plainData bytes], (CC_LONG)[plainData length], hashBytes)) {
return NO;
}

OSStatus status = SecKeyRawVerify(publicKey,
kSecPaddingPKCS1SHA1,
hashBytes,
hashBytesSize,
signedHashBytes,
signedHashBytesSize);

return status == errSecSuccess;
}

- (SecKeyRef)getPublicKey {

NSString * path = [[NSBundle mainBundle]pathForResource:@"Xpay" ofType:@"pfx"];
NSData * data = [NSData dataWithContentsOfFile:path];

SecIdentityRef myIdentity;
SecTrustRef myTrust;
extractIdentityAndTrust((__bridge CFDataRef)data, &myIdentity, &myTrust);

SecKeyRef publicKey;
publicKey = SecTrustCopyPublicKey(myTrust);

return publicKey;
}
OSStatus extractIdentityAndTrust(CFDataRef inP12data, SecIdentityRef *identity, SecTrustRef *trust)
{
OSStatus securityError = errSecSuccess;

CFStringRef password = CFSTR("xxxx");
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };

CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);

CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
securityError = SecPKCS12Import(inP12data, options, &items);

if (securityError == 0) {
CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex(items, 0);
const void *tempIdentity = NULL;
tempIdentity = CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemIdentity);
*identity = (SecIdentityRef)tempIdentity;
const void *tempTrust = NULL;
tempTrust = CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemTrust);
*trust = (SecTrustRef)tempTrust;
}

if (options) {
CFRelease(options);
}

return securityError;
}

参考
http://blog.csdn.net/justinjing0612/article/details/7786250
https://developer.apple.com/library/mac/documentation/Security/Conceptual/CertKeyTrustProgGuide/iPhone_Tasks/iPhone_Tasks.html
https://xiuchundao.me/post/ios-read-cert-with-security-framework

热评文章