Iphone 从密钥链中的密钥对中提取公钥 问题是:检索公钥

Iphone 从密钥链中的密钥对中提取公钥 问题是:检索公钥,iphone,objective-c,ios,rsa,ios5,Iphone,Objective C,Ios,Rsa,Ios5,对于iPhone应用程序,我需要创建一个rsa密钥对,将其存储在密钥链中并检索公钥 幸运的是,苹果发布了一个示例,其中我需要的所有东西都可以找到SecKeyWrapper类、generateKeyPair函数和getPublicKeyBits函数 但是在尝试使用这些函数之后,我总是为不同的密钥对获得相同的公钥输出,而不是为不同的密钥对获得不同的公钥位 my generateKeyPair和getPublicKeyBits函数的实现: 我首先通过调用generateKeyPairWithKeySi

对于iPhone应用程序,我需要创建一个rsa密钥对,将其存储在密钥链中并检索公钥

幸运的是,苹果发布了一个示例,其中我需要的所有东西都可以找到SecKeyWrapper类、generateKeyPair函数和getPublicKeyBits函数

但是在尝试使用这些函数之后,我总是为不同的密钥对获得相同的公钥输出,而不是为不同的密钥对获得不同的公钥位

my generateKeyPair和getPublicKeyBits函数的实现: 我首先通过调用generateKeyPairWithKeySizeInBits创建一个密钥对,它似乎工作得很好,然后我用getPublicKeyBits提取公钥位并将它们记录下来

- (void) generateKeyPairWithKeySizeInBits:(int)bits withPublicIdentifier:(NSString     *)publicIdentifier andPrivateIdentifier:(NSString *)privateIdentifier
{

    NSLog(@"begin generating key...");
    OSStatus status = noErr;

    NSMutableDictionary* privateKeyAttr = [[NSMutableDictionary alloc] init];
    NSMutableDictionary* publicKeyAttr = [[NSMutableDictionary alloc] init];
    NSMutableDictionary* keyPairAttr = [[NSMutableDictionary alloc] init];

    NSData* publicTag = [publicIdentifier dataUsingEncoding:NSUTF8StringEncoding];
    NSData* privateTag = [privateIdentifier dataUsingEncoding:NSUTF8StringEncoding];

    SecKeyRef publicKey = NULL;
    SecKeyRef privateKey = NULL;

    [keyPairAttr setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id) kSecAttrKeyType];
    [keyPairAttr setObject:[NSNumber numberWithInt:bits] forKey:(__bridge id) kSecAttrKeySizeInBits];

    [privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id) kSecAttrIsPermanent];
    [privateKeyAttr setObject:privateTag forKey:(__bridge id) kSecAttrApplicationTag];

    [publicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent];
    [publicKeyAttr setObject:publicTag forKey:(__bridge id)kSecAttrApplicationTag];

    [keyPairAttr setObject:privateKeyAttr forKey:(__bridge id)kSecPrivateKeyAttrs];
    [keyPairAttr setObject:publicKeyAttr forKey:(__bridge id)kSecPublicKeyAttrs];

    SecItemDelete((__bridge CFDictionaryRef)keyPairAttr);

    status = SecKeyGeneratePair((__bridge CFDictionaryRef) keyPairAttr, &publicKey, &privateKey);

    if(status != noErr){
        NSLog(@"status = %@",status);
    }
    if(publicKey){
        NSLog(@"public key %@",publicKey);
    }

    if(privateKey){
        NSLog(@"private key %@",privateKey);
    }

    [self getPublicKeyBits:publicIdentifier];
}


- (NSData *)getPublicKeyBits: (NSString*) publicKeyIdentifier {

    OSStatus sanityCheck = noErr;
    NSData * publicKeyBits = nil;
    CFTypeRef pk;
    NSMutableDictionary * queryPublicKey = [[NSMutableDictionary alloc] init];

    NSData* publicTag = [publicKeyIdentifier dataUsingEncoding:NSUTF8StringEncoding];

    // Set the public key query dictionary.
    [queryPublicKey setObject:(__bridge_transfer id)kSecClassKey forKey:(__bridge_transfer id)kSecClass];

    [queryPublicKey setObject:publicTag forKey:(__bridge_transfer id)kSecAttrApplicationTag];
    [queryPublicKey setObject:(__bridge_transfer id)kSecAttrKeyTypeRSA forKey:(__bridge_transfer id)kSecAttrKeyType];
    [queryPublicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge_transfer id)kSecReturnData];

    // Get the key bits.
    sanityCheck = SecItemCopyMatching((__bridge_retained CFDictionaryRef)queryPublicKey, &pk);
    if (sanityCheck != noErr)
    {
        publicKeyBits = nil;
    }
    publicKeyBits = (__bridge_transfer NSData*)pk;
    NSLog(@"public bits %@",publicKeyBits);

    return publicKeyBits;
}
输出公共位部分最后一行始终相同:
公钥将包含两个组件:指数和模。您可以尝试此操作

获取PublickeyBits方法后

- (NSData *)getPublicKeyExp
{
NSData* pk = [self getPublicKeyBits];
if (pk == NULL) return NULL;

int iterator = 0;

iterator++; // TYPE - bit stream - mod + exp
[self derEncodingGetSizeFrom:pk at:&iterator]; // Total size

iterator++; // TYPE - bit stream mod
int mod_size = [self derEncodingGetSizeFrom:pk at:&iterator];
iterator += mod_size;

iterator++; // TYPE - bit stream exp
int exp_size = [self derEncodingGetSizeFrom:pk at:&iterator];

return [pk subdataWithRange:NSMakeRange(iterator, exp_size)];
return pk;
}
- (NSData *)getPublicKeyMod
{
NSData* pk = [self getPublicKeyBits];
if (pk == NULL) return NULL;

int iterator = 0;

iterator++; // TYPE - bit stream - mod + exp
[self derEncodingGetSizeFrom:pk at:&iterator]; // Total size

iterator++; // TYPE - bit stream mod
int mod_size = [self derEncodingGetSizeFrom:pk at:&iterator];

return [pk subdataWithRange:NSMakeRange(iterator, mod_size)];
return pk;
NSLog(@"public size: %d",pk.length);
}

- (int)derEncodingGetSizeFrom:(NSData*)buf at:(int*)iterator
{
const uint8_t* data = [buf bytes];
int itr = *iterator;
int num_bytes = 1;
int ret = 0;

if (data[itr] > 0x80) {
    num_bytes = data[itr] - 0x80;
    itr++;
}

for (int i = 0 ; i < num_bytes; i++) 
    ret = (ret * 0x100) + data[itr + i];

*iterator = itr + num_bytes;
return ret;
}

因此,您的SecItemDelete代码无法按预期工作。显然,如果出于测试目的您想删除密钥链中的所有项目,您应该查看AdvancedURLConnections示例代码中的-[Credentials resetCredentials]方法中的代码

在调试过程中,您可能还会发现-dumpCredentials方法很方便


因此,SecItemDelete的问题意味着每次运行应用程序时,SecKeyGeneratePair都会生成一组新的密钥。这些键中的每一个都有相同的应用程序标记,这使得它无法确定-getPublicKeyBits:中的SecItemCopyMatching调用返回的键。事实证明,在当前的系统软件上,您总是会得到第一个密钥,因此您总是会得到相同的公钥位。

对于生成公钥,您可以使用此链接感谢您的努力,但它并不能解决问题:公钥位保持不变,因此对于函数,指数和模将保持不变,我也不明白,你试过用那个链接吗
- (NSData *)getPublicKeyExp
{
NSData* pk = [self getPublicKeyBits];
if (pk == NULL) return NULL;

int iterator = 0;

iterator++; // TYPE - bit stream - mod + exp
[self derEncodingGetSizeFrom:pk at:&iterator]; // Total size

iterator++; // TYPE - bit stream mod
int mod_size = [self derEncodingGetSizeFrom:pk at:&iterator];
iterator += mod_size;

iterator++; // TYPE - bit stream exp
int exp_size = [self derEncodingGetSizeFrom:pk at:&iterator];

return [pk subdataWithRange:NSMakeRange(iterator, exp_size)];
return pk;
}
- (NSData *)getPublicKeyMod
{
NSData* pk = [self getPublicKeyBits];
if (pk == NULL) return NULL;

int iterator = 0;

iterator++; // TYPE - bit stream - mod + exp
[self derEncodingGetSizeFrom:pk at:&iterator]; // Total size

iterator++; // TYPE - bit stream mod
int mod_size = [self derEncodingGetSizeFrom:pk at:&iterator];

return [pk subdataWithRange:NSMakeRange(iterator, mod_size)];
return pk;
NSLog(@"public size: %d",pk.length);
}

- (int)derEncodingGetSizeFrom:(NSData*)buf at:(int*)iterator
{
const uint8_t* data = [buf bytes];
int itr = *iterator;
int num_bytes = 1;
int ret = 0;

if (data[itr] > 0x80) {
    num_bytes = data[itr] - 0x80;
    itr++;
}

for (int i = 0 ; i < num_bytes; i++) 
    ret = (ret * 0x100) + data[itr + i];

*iterator = itr + num_bytes;
return ret;
}