【问题标题】:How to find out the modulus and exponent of RSA Public Key on iPhone/Objective C如何在 iPhone/Objective C 上找出 RSA 公钥的模数和指数
【发布时间】:2011-04-19 21:27:13
【问题描述】:

是否有可能找出使用 SecKeyGeneratePair(一般的安全框架)创建的公钥的模数和指数?

【问题讨论】:

  • 对于任何关心的人:我前段时间通过使用 OpenSSL 解决了我的问题。
  • 请分享解决方案...这会有所帮助:)

标签: iphone objective-c cocoa-touch encryption rsa


【解决方案1】:

对此我一头雾水,但这是我找到的解决方案(不使用任何外部包)。

首先,转到 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;
}

【讨论】:

  • 非常好的一个。我暂时不会对其进行测试,因为现在一切都通过 OpenSSL 运行(并且不会改变),但我很惊讶有人找到了解决方案。非常感谢 Yoav 的回答!
  • @Yoav 知道如何做相反的事情吗? (从模数和指数组装公钥)
  • @Yoav 有没有办法获取私钥的模数和指数?
  • 你们知道如果我使用这段代码我的应用会被拒绝吗?苹果对他们的加密处理非常严格
【解决方案2】:

我尝试了这种方法,它可以很好地提取指数。正如预期的那样,它的大小为 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;
}

【讨论】:

  • ASN.1 编码是 2 的补码。您可能遇到过将高位设置为 128 字节的情况。这将使该值成为负 ASN.1 整数。所以在前面加上 0x00 使其成为正 ASN.1 整数。 0x00 映射数据 129 字节。 (当然只是推测)。
  • 是否有做虎钳的过程来从模数和指数生成公钥?
【解决方案3】:

类似下面的内容更可靠:

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

【讨论】:

    【解决方案4】:

    我在开始时删除了那个额外的字节,现在它可以正常工作了。在我的例子中,它总是提取 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)];
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-22
      • 2020-08-13
      • 1970-01-01
      • 2012-07-17
      • 2015-10-13
      • 2014-04-16
      • 1970-01-01
      相关资源
      最近更新 更多