Как узнать модуль и показатель открытого ключа RSA на iPhone / Задача C - PullRequest
8 голосов
/ 01 октября 2010

Существует ли возможный способ узнать модуль и показатель степени открытого ключа, созданного с помощью SecKeyGeneratePair (платформа безопасности в целом)?

Ответы [ 4 ]

13 голосов
/ 28 ноября 2010

Я решил об этом, но вот решение, которое я нашел (без использования внешних пакетов).

Сначала перейдите к примеру Apple CryptoExercise. Загрузите класс "SecKeyWrapper" оттуда. Интересная функция в этом классе - getPublicKeyBits.

Ссылка на пример: http://developer.apple.com/library/ios/#samplecode/CryptoExercise/Introduction/Intro.html

Полученные вами биты - это открытый ключ в кодировке DER (wiki it), содержащий как модуль, так и exp. Вот код, который расшифрует его для вас, довольно просто:

- (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)];
}

- (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)];
}

- (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;
}
2 голосов
/ 15 декабря 2012

Я попробовал этот подход, и он отлично работает для извлечения показателя. Он имеет размер 3 байта, как и ожидалось, но извлеченный модуль имеет неправильный размер. Размер модуля составляет 129 байт вместо 128 байт.

Код выглядит следующим образом:

- (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;
}


- (NSData *)getPublicKeyExp
{
    NSData* pk = [self getPublicKeyBits:@"RSA Public Key"];
    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:@"RSA Public Key"];
    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;
}
0 голосов
/ 20 марта 2015

Я удалил этот лишний байт в начале, теперь он работает нормально.В моем случае он всегда извлекал модуль 129 байтов.

- (NSData *)getPublicKeyModFromKeyData:(NSData*)pk
{
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)];
NSData* subData=[pk subdataWithRange:NSMakeRange(iterator, mod_size)];
return  [subData subdataWithRange:NSMakeRange(1, subData.length-1)];

}
0 голосов
/ 18 февраля 2015

Что-то вроде следующего гораздо надежнее:

+ (NSInteger)keyModulusSize:(NSData *)keyData
{
    NSString *randomTag = [NSString ptk_randomStringOfLength:32];
    SecKeyRef key = [self addPublicKeyRef:keyData withTag:randomTag];

    NSInteger size = 0;
    if (key) {
        size = SecKeyGetBlockSize(key);
        [self removePublicKeyRef:randomTag];
    }

    return size;
}
...