使用Objective C在iOS中使用公钥加密或签名字符串 [英] encrypt or sign string with public key in iOS with Objective C

查看:687
本文介绍了使用Objective C在iOS中使用公钥加密或签名字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一把私钥。文本文件以---开始私钥......开头。



我想用该密钥加密NSString。因为它的私钥,最好叫它签署一个NSString。



这可以在没有任何外部框架的情况下完成吗?



结果应该等同于php openssl_sign函数。

解决方案

没有外部源或组件,您可以更轻松地解决这个问题。



我发现了如何分享它,以便我可以帮助别人。


  1. 您需要加载密钥文件SecKeyRef并安全地使用maxPlainLen



 
NSString * resourcePath = [[NSBundle mainBundle] pathForResource:privateKeyResourceName ofType:@p12];
NSData * p12Data = [NSData dataWithContentsOfFile:resourcePath];

NSMutableDictionary * options = [[NSMutableDictionary alloc] init];

SecKeyRef privateKeyRef = NULL;

//更改为您在此处使用的实际密码
[options setObject:@_ YOURPASSWORDHERE__forKey:(__ bridge id)kSecImportExportPassphrase];

CFArrayRef items = CFArrayCreate(NULL,0,0,NULL);

OSStatus securityError = SecPKCS12Import((__ bridge CFDataRef)p12Data,
(__ bridge CFDictionaryRef)options,&items);

if(securityError == noErr && CFArrayGetCount(items)> 0){
CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items,0);
SecIdentityRef identityApp =
(SecIdentityRef)CFDictionaryGetValue(identityDict,
kSecImportItemIdentity);

securityError = SecIdentityCopyPrivateKey(identityApp,&privateKeyRef);
if(securityError!= noErr){
privateKeyRef = NULL;
}
}
CFRelease(items);

privateKey = privateKeyRef;
maxPlainLen = SecKeyGetBlockSize(privateKey) - 12;




  1. 您可以使用类别方法将NSString转换为SHA1



 
- (NSData *)toSha1AsData {
// PHP使用ASCII编码,而不是UTF
const char * s = [self cStringUsingEncoding:NSASCIIStringEncoding];
NSData * keyData = [NSData dataWithBytes:s length:strlen(s)];

//这是目的地
uint8_t摘要[CC_SHA1_DIGEST_LENGTH] = {0};
//这个函数执行哈希数据的无键SHA1哈希
CC_SHA1(keyData.bytes,keyData.length,digest);

//现在转换为NSData结构使其再次可用
NSData * out = [NSData dataWithBytes:摘要长度:CC_SHA1_DIGEST_LENGTH]

退出;
}




  1. 现在你可以用这种方法签署你的SHA1

 



(NSData *)signSha1Data :(NSData *)data {
size_t plainLen = [data length];
if(plainLen> maxPlainLen)
{
NSLog(@content(%ld)太长,必须<%ld,plainLen,maxPlainLen);
返回零;
}

void * plain = malloc(plainLen);
[data getBytes:plain
length:plainLen];

size_t cipherLen = 128; //当前RSA密钥长度设置为128字节
void * cipher = malloc(cipherLen);

OSStatus returnCode = SecKeyRawSign(privateKey,kSecPaddingPKCS1SHA1,
plain,plainLen,cipher,& cipherLen);

NSData * result = nil;
if(returnCode!= 0){
NSLog(@SecKeyEncrypt fail。错误代码:%ld,returnCode);
}
else {
result = [NSData dataWithBytes:cipher
length:cipherLen];
}

免费(普通);
免费(密码);

返回结果;
}

它工作得非常好,没有任何外部库。没有必要编译一些奇怪的openssl东西。


i have a private key. Text File that begins like "--- begin private key..."

i want to use that key to encrypt an NSString. since its the private key, better call it sign an NSString.

can this be done without any external frameworks?

the result should be equivalent to the php openssl_sign function.

解决方案

You can solve this much easier with no external sources or components.

I found out how and wanted to share it so i may help others.

  1. You need to load the key file a SecKeyRef and safe the maxPlainLen as well

    NSString *resourcePath = [[NSBundle mainBundle] pathForResource:privateKeyResourceName ofType:@"p12"];
    NSData *p12Data = [NSData dataWithContentsOfFile:resourcePath];

    NSMutableDictionary * options = [[NSMutableDictionary alloc] init];

    SecKeyRef privateKeyRef = NULL;

    //change to the actual password you used here
    [options setObject:@"_YOURPASSWORDHERE__" forKey:(__bridge id)kSecImportExportPassphrase];

    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);

    OSStatus securityError = SecPKCS12Import((__bridge CFDataRef) p12Data,
                                             (__bridge CFDictionaryRef)options, &items);

    if (securityError == noErr && CFArrayGetCount(items) > 0) {
        CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
        SecIdentityRef identityApp =
        (SecIdentityRef)CFDictionaryGetValue(identityDict,
                                             kSecImportItemIdentity);

        securityError = SecIdentityCopyPrivateKey(identityApp, &privateKeyRef);
        if (securityError != noErr) {
            privateKeyRef = NULL;
        }
    }
    CFRelease(items);

    privateKey = privateKeyRef;
    maxPlainLen = SecKeyGetBlockSize(privateKey) - 12;

  1. You can convert NSString with a category method to SHA1

    - (NSData*)toSha1AsData {
        // PHP uses ASCII encoding, not UTF
        const char *s = [self cStringUsingEncoding:NSASCIIStringEncoding];
        NSData *keyData = [NSData dataWithBytes:s length:strlen(s)];

        // This is the destination
        uint8_t digest[CC_SHA1_DIGEST_LENGTH] = {0};
        // This one function does an unkeyed SHA1 hash of your hash data
        CC_SHA1(keyData.bytes, keyData.length, digest);

        // Now convert to NSData structure to make it usable again
        NSData *out = [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH]

        return out;
    }

  1. Now you can sign your SHA1 with this method

(NSData *)signSha1Data:(NSData *)data { size_t plainLen = [data length]; if (plainLen > maxPlainLen) { NSLog(@"content(%ld) is too long, must < %ld", plainLen, maxPlainLen); return nil; } void *plain = malloc(plainLen); [data getBytes:plain length:plainLen]; size_t cipherLen = 128; // currently RSA key length is set to 128 bytes void *cipher = malloc(cipherLen); OSStatus returnCode = SecKeyRawSign(privateKey, kSecPaddingPKCS1SHA1, plain, plainLen, cipher, &cipherLen); NSData *result = nil; if (returnCode != 0) { NSLog(@"SecKeyEncrypt fail. Error Code: %ld", returnCode); } else { result = [NSData dataWithBytes:cipher length:cipherLen]; } free(plain); free(cipher); return result; }

It works very well and without any external libs. There is no need to compile some wierd openssl stuff.

这篇关于使用Objective C在iOS中使用公钥加密或签名字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆