5

如何在不使用任何第三方代码(例如)开放 SSL 的情况下在 iOS 中使用公钥验证数字签名?

我需要使用公钥验证 iOS App 中的数字签名。有人可以帮助我如何在不使用第三方软件的情况下实现这一目标。

我正在尝试以下代码,但问题是我的应用程序中没有证书,因此无法创建SecTrustRef

代码:

    NSString *certPath              = [[NSBundle mainBundle] pathForResource:@"yyy" 
                                                             ofType:@"xxx"];
    SecCertificateRef myCertificate = nil;
    NSData *certificateData         = [[NSData alloc] initWithContentsOfFile :certPath];
    myCertificate                   = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)certificateData);

    SecPolicyRef myPolicy           = SecPolicyCreateBasicX509();
    SecTrustRef trustRef;
    SecTrustCreateWithCertificates(myCertificate, myPolicy, &trustRef);
    SecKeyRef keyRef      = SecTrustCopyPublicKey (trustRef);


    BOOL status = SecKeyRawVerify (keyRef,
                              kSecPaddingPKCS1SHA1,
                              (const uint8_t *)[data bytes],
                              (size_t)[data length],
                              (const uint8_t *)[signature bytes],
                              (size_t)[signature length]
                              );

我有以下内容:

  • 公钥(NSString*)
  • 签名(NSString*)
  • 数据(NSString*)

如果我不想使用 ant 第三方开源,请帮助我在 iOS SDK 中的所有选项。

4

4 回答 4

1

您可以使用 openSSL 将您的公钥打包在 X509 证书中,以便轻松使用 iOS 内置功能:

openssl req -x509 -out public_key.pem -outform pem -new -newkey rsa:2048 -keyout private_key.pem 

PEM 格式是 base64 编码的,您可以将 -outform 切换为 DER 以获取二进制文件。您可以通过将 const NSString 添加到您的程序并使用此函数将类别添加到 NSData 来导入 PEM 格式:

- (id) initWithBase64EncodedString:(NSString *) string {
    NSMutableData *mutableData = nil;

    if( string ) {
        unsigned long ixtext = 0;
        unsigned long lentext = 0;
        unsigned char ch = 0;
        unsigned char inbuf[4], outbuf[3]; // buffer sizes fixed by AOL LLC
        short i = 0, ixinbuf = 0;
        BOOL flignore = NO;
        BOOL flendtext = NO;
        NSData *base64Data = nil;
        const unsigned char *base64Bytes = nil;

        // Convert the string to ASCII data.
        base64Data = [string dataUsingEncoding:NSASCIIStringEncoding];
        base64Bytes = [base64Data bytes];
        mutableData = [NSMutableData dataWithCapacity:[base64Data length]];
        lentext = [base64Data length];

        while( YES ) {
            if( ixtext >= lentext ) break;
            ch = base64Bytes[ixtext++];
            flignore = NO;

            if( ( ch >= 'A' ) && ( ch <= 'Z' ) ) ch = ch - 'A';
            else if( ( ch >= 'a' ) && ( ch <= 'z' ) ) ch = ch - 'a' + 26;
            else if( ( ch >= '0' ) && ( ch <= '9' ) ) ch = ch - '0' + 52;
            else if( ch == '+' ) ch = 62;
            else if( ch == '=' ) flendtext = YES;
            else if( ch == '/' ) ch = 63;
            else flignore = YES;

            if( ! flignore ) {
                short ctcharsinbuf = 3;
                BOOL flbreak = NO;

                if( flendtext ) {
                    if( ! ixinbuf ) break;
                    if( ( ixinbuf == 1 ) || ( ixinbuf == 2 ) ) ctcharsinbuf = 1;
                    else ctcharsinbuf = 2;
                    ixinbuf = 3;
                    flbreak = YES;
                }

                inbuf [ixinbuf++] = ch;

                if( ixinbuf == 4 ) {
                    ixinbuf = 0;
                    outbuf [0] = ( inbuf[0] << 2 ) | ( ( inbuf[1] & 0x30) >> 4 );
                    outbuf [1] = ( ( inbuf[1] & 0x0F ) << 4 ) | ( ( inbuf[2] & 0x3C ) >> 2 );
                    outbuf [2] = ( ( inbuf[2] & 0x03 ) << 6 ) | ( inbuf[3] & 0x3F );

                    for( i = 0; i < ctcharsinbuf; i++ )
                        [mutableData appendBytes:&outbuf[i] length:1];
                }

                if( flbreak )  break;
            }
        }
    }

    self = [self initWithData:mutableData];
    return self;
}

当然,如果您想使用现有的公钥,您可以将此文件拉入 certificateData,只需将其拉出并使用 openSSL 以 X509 证书格式写入

$ openssl rsa -in id_rsa -out pub.der -outform DER -pubout

祝你好运

于 2013-10-08T10:22:33.983 回答
0

如果你的密钥数据打包成PKCS12数据,使用SecPKCS12Import导入,使用公钥。

于 2013-03-21T19:47:55.097 回答
0

您需要将数据的摘要(哈希)传递给验证函数。请参阅iOS:使用证书和签名验证文件 - 公钥错误,验证失败

于 2014-01-23T16:26:37.287 回答
0
@interface HDSecurityPolicy :AFSecurityPolicy
@end

@implementation HDSecurityPolicy
///pem formate(base64) ->  NSData
- (void)setPinnedCertificates:(NSSet *)pinnedCertificates {
    [super setPinnedCertificates:pinnedCertificates];
    if (self.pinnedCertificates) {
        NSMutableSet *mutablePinnedPublicKeys = [NSMutableSet setWithCapacity:[self.pinnedCertificates count]];
        for (NSData *pubCertificate in self.pinnedCertificates) {
            id publicKey = [HDSecurityPolicy publicSecKeyFromKeyBits:pubCertificate];
            if (!publicKey) {
                continue;
            }
            [mutablePinnedPublicKeys addObject:publicKey];
        }
        [self setValue:mutablePinnedPublicKeys forKey:@"pinnedPublicKeys"];
    }
}

// 从公钥证书文件中获取到公钥的SecKeyRef指针
+ (id)publicSecKeyFromKeyBits:(NSData *)givenData {
    NSMutableDictionary *options = [NSMutableDictionary dictionary];
    options[(__bridge id)kSecAttrKeyType] = (__bridge id) kSecAttrKeyTypeRSA;
    options[(__bridge id)kSecAttrKeyClass] = (__bridge id) kSecAttrKeyClassPublic;

    NSError *error = nil;
    CFErrorRef ee = (__bridge CFErrorRef)error;
    ////'SecKeyCreateWithData' is only available on iOS 10.0 or newer
    id ret = (__bridge_transfer id)SecKeyCreateWithData((__bridge CFDataRef)givenData, (__bridge CFDictionaryRef)options, &ee);
    if (error) {
        return nil;
    }
    return ret;
}
@end
于 2019-07-04T10:09:49.790 回答