简体   繁体   中英

Convert RSA Public key (2048 bit) from XML format to DER ASN.1 public key for iOS

Am trying to create SecKeyRef from PublicKey (2048 bits) data shared by C# in XML format. The data looks like this:

<Modulus>yLgpOFtg14GjDdle0xha2JCbYrpmKCpXcv+zFx2pi6OlIF8cOSXF6dE19W15+WfuCc2SznVQlVDOLp/NlPGLXKN5L47XYQrPpcls8/xp2PYYW7hjezx7Ig6+WDJnUxSbWgxZQMaiyO1XbCKll5yT2AxUj4od/DfylsVe8ljq154rEb+vCjr/LDpxExijHouJYDNqFV1jglWHWfftBQAzEZADPx7NpHsgXSYrFeVY/WH38GIlyO8FvGWIuDiwyRrHUEXhljmBqAJ3lgULyik3ShfjpN1W4h7BbzFs27mpiAPMtPgToADPNzOadRWFJQjeVVknIq5g6SHHnaZK8wBwrQ==</Modulus><Exponent>AQAB</Exponent>]]>"

I have followed the Convert XML Dsig format to DER ASN.1 public key link, which works only for 1024 bits key but the same logic is failing to DER encode the above key (2048 bits). Though I could see in the comments that the conversion logic needs to be modified for 256 bytes key, am not able to succeed with alterations!

I have also tried Generate Public Key From Modulus & Exponent on iOS using OpenSSL library, but failed to generate RSA object with this! Below is the sample:

NSString *mod = @"yLgpOFtg14GjDdle0xha2JCbYrpmKCpXcv+zFx2pi6OlIF8cOSXF6dE19W15+WfuCc2SznVQlVDOLp/NlPGLXKN5L47XYQrPpcls8/xp2PYYW7hjezx7Ig6+WDJnUxSbWgxZQMaiyO1XbCKll5yT2AxUj4od/DfylsVe8ljq154rEb+vCjr/LDpxExijHouJYDNqFV1jglWHWfftBQAzEZADPx7NpHsgXSYrFeVY/WH38GIlyO8FvGWIuDiwyRrHUEXhljmBqAJ3lgULyik3ShfjpN1W4h7BbzFs27mpiAPMtPgToADPNzOadRWFJQjeVVknIq5g6SHHnaZK8wBwrQ==";

BIGNUM *modulus = BN_new();
int res = BN_hex2bn(&modulus,[mod cStringUsingEncoding:NSUTF8StringEncoding]);

BIGNUM *exponent = BN_new();
NSString *exp = @"AQAB";
res = BN_hex2bn(&exponent,[exp cStringUsingEncoding:NSUTF8StringEncoding]);

RSA *rsa = RSA_new();

rsa->n = BN_new();
BN_copy(rsa->n,modulus);
rsa->e = BN_new();
BN_copy(rsa->e,exponent);
rsa->iqmp=NULL;
rsa->d=NULL;
rsa->p=NULL;
rsa->q=NULL;

FILE *fp = fopen("/publicKey.pem", "wb");
int suc = PEM_write_RSAPublicKey(fp, rsa, NULL, NULL, 0, 0, NULL);

The generated publicKey.pem file is apparently empty! It would be great if anyone can help me to import XML RSA public key into iOS SecKetRef object.

Thanks in advance :)

I could successfully resolve this issue with both the approaches mentioned above. Here is my solution:

Approach # 1.Convert XML keys to ASN.1 DER format worked with 256 bytes key (2048 bits) with this link. https://github.com/meinside/iphonelib/blob/master/security/CryptoUtil.m#L67

Approach # 2. Could successfully encrypt with the RSA object (reference: Generate Public Key From Modulus & Exponent on iOS using OpenSSL ) created with following code:

`NSString *mod = @"yLgpOFtg14GjDdle0xha2JCbYrpmKCpXcv+zFx2pi6OlIF8cOSXF6dE19W15+WfuCc2SznVQlVDOLp/NlPGLXKN5L47XYQrPpcls8/xp2PYYW7hjezx7Ig6+WDJnUxSbWgxZQMaiyO1XbCKll5yT2AxUj4od/DfylsVe8ljq154rEb+vCjr/LDpxExijHouJYDNqFV1jglWHWfftBQAzEZADPx7NpHsgXSYrFeVY/WH38GIlyO8FvGWIuDiwyRrHUEXhljmBqAJ3lgULyik3ShfjpN1W4h7BbzFs27mpiAPMtPgToADPNzOadRWFJQjeVVknIq5g6SHHnaZK8wBwrQ==";

NSString *exp = @"AQAB";

NSData *modBits = [[NSData alloc] initWithBase64EncodedString:mod options:NSDataBase64DecodingIgnoreUnknownCharacters];
NSData *expBits = [[NSData alloc] initWithBase64EncodedString:exp options:NSDataBase64DecodingIgnoreUnknownCharacters];

unsigned char *modBin = (unsigned char *)malloc(modBits.length);
[modBits getBytes:modBin length:modBits.length];

unsigned char *expBin = (unsigned char *)malloc(expBits.length);
[expBits getBytes:expBin length:expBits.length];


BIGNUM *returnValue = BN_new();
BIGNUM *modulus = BN_bin2bn(modBin, modBits.length, returnValue);
BIGNUM *exponent = BN_bin2bn(expBin, expBits.length, NULL);

RSA *rsa = RSA_new();
rsa->n = BN_new();
BN_copy(rsa->n,modulus);
rsa->e = BN_new();
BN_copy(rsa->e,exponent);
rsa->iqmp=NULL;
rsa->d=NULL;
rsa->p=NULL;
rsa->q=NULL;


unsigned char *orgTxt = (unsigned char*)strdup("Hello World");

int lenrsa = RSA_size( rsa ) - 11; // man RSA_public_encrypt for the -11

unsigned char *encrText = (unsigned char *)malloc(lenrsa);
int result = RSA_public_encrypt(strlen((const char*)orgTxt), orgTxt, encrText, rsa,RSA_PKCS1_PADDING);

Be sure of the glen param of RSA_public_encrypt API, it depends on the padding used. man RSA_public_encrypt` for more details.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM