Is there a possible way to find out the modulus and exponent of the Public Key, created with SecKeyGeneratePair (the Security Framework in general)?
-
For anyone who cares: I solved my problem some time ago, by using OpenSSL. – zhar Oct 22 '10 at 12:42
-
1please share the solution ... it will be helpful :) – Devarshi May 12 '14 at 10:48
4 Answers
Busted my head on this, but here's a solution I've found (without using any external packages).
First, go to Apple's CryptoExercise example. Download the "SecKeyWrapper" class from there. The interesting function in that class is getPublicKeyBits.
Link to the example: http://developer.apple.com/library/ios/#samplecode/CryptoExercise/Introduction/Intro.html
The bits you will receive is a DER encoded (wiki it) public key containing both the modulus and exp. Here's a code that will decode it for you, pretty easy:
- (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;
}

- 156
- 1
- 3
-
1Very nice one. I won't test it for some time, because everything is running via OpenSSL now (and that wont change), but I am very suprised that someone found a solution for this. Thank you very much for the answer Yoav! – zhar Nov 30 '10 at 12:30
-
@Yoav Any idea how to do the reverse? (assembling public key from modulus and exponent) – pixelfreak Oct 20 '13 at 04:48
-
@Yoav is there a way to get the modulus and exponent for private key? – Christian Sep 11 '14 at 23:36
-
Do you guys know if my app will get rejected if I use this piece of code? Apple is pretty strict about their Crypto handling – Oz Shabat Apr 20 '21 at 10:22
I tried this approach and it works fine for extracting the exponent. It is 3 bytes in size as expected but the extracted modulus is not the correct size. The size of the modulus is 129 bytes instead of 128 bytes.
The code is as follows:
- (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;
}

- 41
- 4
-
ASN.1 encoding is 2's compliment. You likely encountered a case where the high bit was set with 128 bytes. That would make the value a negative ASN.1 integer. So 0x00 was prepended to make it a positive ASN.1 integer. The 0x00 mage the data 129 bytes. (Just speculating, of course). – jww Feb 07 '13 at 10:41
-
Is there to do the vise verse process to generate the public key from modulus and exponent? – Sarah Nov 18 '13 at 13:25
Something like the following is much more reliable:
+ (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;
}

- 23,351
- 11
- 76
- 89
I removed that extra byte at the beginning, now it works fine. In my case it was always extracting 129 bytes modulus.
- (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)];
}

- 1,305
- 16
- 24