IOS下使用RSA加密与PHP通信,使用服务器下发的NSString类型参数

第一次写博客,不知道写点什么会比较好,不知道写点什么会显得自己比较牛逼,哈哈,开个玩笑了,不过确实是第一次写博客,只好是先从最近遇到的问题开始写起吧。

最近因为有涉及密码上传到服务器的需求,而服务器那边要求必须用RSA加密,这件事情让我头大了半天。至于服务器为什么一定要选择RSA,我也不懂,维基上说是安全,但却让我这边费了一番时间,

废话不多说,切入正题,我在网上看到的别人的写法大部分是自己在客户端这边生成证书,然后利用证书进行加密,这与之前服务器说用他给的NSString公钥大相径庭,所以这样的帖子直接被我忽略了。但同时也确实找到了很多不错的利用NSString的例子,只不过由于我理解不够深入,始终不能通过NSString获得SeckeyRef,我先在这贴出来。

http://stackoverflow.com/questions/1536894/converting-raw-rsa-key-value-to-seckeyref-object-for-encryption

The following code comes from Apple's CryptoExercise example, in SecKeyWrapper.m. It assumes the "publicKey" NSData object is the binary DER-encoded ASN.1 object, not base-64 encoded. So you'll have to get a base-64 decoder and apply it first. You might also want to read this post in the Apple Developer Forums.

- (SecKeyRef)addPeerPublicKey:(NSString *)peerName keyBits:(NSData *)publicKey {
    OSStatus sanityCheck = noErr;
    SecKeyRef peerKeyRef = NULL;
    CFTypeRef persistPeer = NULL;

    LOGGING_FACILITY( peerName != nil, @"Peer name parameter is nil." );
    LOGGING_FACILITY( publicKey != nil, @"Public key parameter is nil." );

    NSData * peerTag = [[NSData alloc] initWithBytes:(const void *)[peerName UTF8String] length:[peerName length]];
    NSMutableDictionary * peerPublicKeyAttr = [[NSMutableDictionary alloc] init];

    [peerPublicKeyAttr setObject:(id)kSecClassKey forKey:(id)kSecClass];
    [peerPublicKeyAttr setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType];
    [peerPublicKeyAttr setObject:peerTag forKey:(id)kSecAttrApplicationTag];
    [peerPublicKeyAttr setObject:publicKey forKey:(id)kSecValueData];
    [peerPublicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnPersistentRef];

    sanityCheck = SecItemAdd((CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef *)&persistPeer);

    // The nice thing about persistent references is that you can write their value out to disk and
    // then use them later. I don't do that here but it certainly can make sense for other situations
    // where you don't want to have to keep building up dictionaries of attributes to get a reference.
    // 
    // Also take a look at SecKeyWrapper's methods (CFTypeRef)getPersistentKeyRefWithKeyRef:(SecKeyRef)key
    // & (SecKeyRef)getKeyRefWithPersistentKeyRef:(CFTypeRef)persistentRef.

    LOGGING_FACILITY1( sanityCheck == noErr || sanityCheck == errSecDuplicateItem, @"Problem adding the peer public key to the keychain, OSStatus == %d.", sanityCheck );

    if (persistPeer) {
        peerKeyRef = [self getKeyRefWithPersistentKeyRef:persistPeer];
    } else {
        [peerPublicKeyAttr removeObjectForKey:(id)kSecValueData];
        [peerPublicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnRef];
        // Let's retry a different way.
        sanityCheck = SecItemCopyMatching((CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef *)&peerKeyRef);
    }

    LOGGING_FACILITY1( sanityCheck == noErr && peerKeyRef != NULL, @"Problem acquiring reference to the public key, OSStatus == %d.", sanityCheck );

    [peerTag release];
    [peerPublicKeyAttr release];
    if (persistPeer) CFRelease(persistPeer);
    return peerKeyRef;
}

 这个方法刚开始我用时仍然无法得到seckeyRef,所以我否定了它,不过现在想想可能是我运用不当。服务器最开始给我返回的NSString不错,可惜只是一个modulus,也就是RSA加密中公钥的e,如果不懂的同学可以先google下RSA。

我将服务器返回给我的这个NSString转成了NSData然后套入到如上方法,结果失败了。屡试屡败,所以原谅我粗浅的认为它错了。后来经过与服务器的沟通得知,服务器这边产生RSA一对秘钥采用的是openssl生成证书的形式,而iOS恰好也支持这样的证书,只不过要采用x509加签,貌似是说iOS没有这样的API,所以就找到了问题的关键,关于openssl生成证书,凡是遇到RSA问题的同学肯定都在找寻的路途中遇到过,大家可以参考这http://www.cnblogs.com/guola/archive/2012/10/30/2746159.html里:http://www.cnblogs.com/guola/archive/2012/10/30/2746159.html

上次写到一半,就被CSDN给封掉了,原因是新用户不允许使用链接。。。。以至于我的思路都断片了,还好有草稿备份了一部分,要不然真不知道自己是怎么死得。。。

继续吧,服务器用openssl生成private.pem,同时生成public.pem文件,然后服务器取出public.pem文件的内容,掐头去尾传给我,何为掐头去尾?pem格式的文件貌似就是在der格式的文件内容中在头和尾加了个标签,去掉即为der格式文件的内容,但是貌似der格式无法用文本编辑器打开,所以我采取了这个较为笨拙的方法,我将其写入自己用openssl生成的证书der格式,这样就可以用网上那些诸多的方法读取到证书中的内容信息了。

贴出我这部分的代码:

- (SecKeyRef) getPublicKey{// 从公钥证书文件中获取到公钥的SecKeyRef指针

    if(_public_key ==nil){

        NSString *publicKeyPath = [[[NSBundlemainBundle]bundlePath]stringByAppendingString:@"/publick_key1.der"];

        if(publicKeyPath == nil)

        {

            NSLog(@"Can not find public_key.der");

            return nil;

        }

        NSData *publickData = [NSDatadataWithContentsOfFile:publicKeyPath];

        publickData = [GTMBase64 decodeData:publickData];

        if(publickData == nil)

        {

            NSLog(@"Can not read from pub.der");

            return nil;

        }        

        SecCertificateRef myCertificate = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridgeCFDataRef)publickData);

        SecPolicyRef myPolicy =SecPolicyCreateBasicX509();

        SecTrustRef myTrust;

        OSStatus status = SecTrustCreateWithCertificates(myCertificate,myPolicy,&myTrust);

        SecTrustResultType trustResult;

        if (status == noErr) {

            status = SecTrustEvaluate(myTrust, &trustResult);

        }

        _public_key = SecTrustCopyPublicKey(myTrust);

        CFRelease(myCertificate);

        CFRelease(myPolicy);

        CFRelease(myTrust);

    }

    //NSLog(@"public_key:%@",_public_key);

    return_public_key;

}

转载请注明出处,谢谢。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值