Как узнать модуль и показатель степени открытого ключа RSA на iPhone / Objective C

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


person zhar    schedule 01.10.2010    source источник
comment
Для всех, кому не все равно: некоторое время назад я решил свою проблему с помощью OpenSSL.   -  person zhar    schedule 22.10.2010
comment
поделитесь пожалуйста решением ... будет полезно :)   -  person Devarshi    schedule 12.05.2014


Ответы (4)


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

Сначала перейдите к примеру 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;
}
person Yoav    schedule 28.11.2010
comment
Очень хороший. Я не буду тестировать его какое-то время, потому что сейчас все работает через OpenSSL (и это не изменится), но я очень удивлен, что кто-то нашел решение для этого. Большое спасибо за ответ Йоав! - person zhar; 30.11.2010
comment
@Yoav Есть идеи, как сделать наоборот? (сборка открытого ключа из модуля и экспоненты) - person pixelfreak; 20.10.2013
comment
@Yoav есть ли способ получить модуль и показатель степени для закрытого ключа? - person Christian; 12.09.2014
comment
Вы, ребята, знаете, будет ли отклонено мое приложение, если я использую этот фрагмент кода? Apple довольно строго относится к обработке криптовалюты - person Oz Shabat; 20.04.2021

Я пробовал этот подход, и он отлично работает для извлечения экспоненты. Как и ожидалось, он имеет размер 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;
}
person Nakul Bali    schedule 15.12.2012
comment
Кодировка ASN.1 - это дополнение 2. Вероятно, вы столкнулись со случаем, когда старший бит был установлен на 128 байтов. Это сделало бы значение отрицательным целым числом ASN.1. Таким образом, 0x00 был добавлен, чтобы сделать его положительным целым числом ASN.1. 0x00 отображает данные 129 байтов. (Конечно, просто догадываюсь). - person jww; 07.02.2013
comment
Должен ли быть процесс тисков для генерации открытого ключа из модуля и экспоненты? - person Sarah; 18.11.2013

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

+ (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;
}
person Joseph Earl    schedule 18.02.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)];

}
person Ozgur Sahin    schedule 20.03.2015