【问题标题】:read RSA public key as bytes via openssl / c / c++通过 openssl / c / c++ 将 RSA 公钥读取为字节
【发布时间】:2013-12-19 05:11:35
【问题描述】:

我正在尝试将 2048 位(256 字节)的 RSA 公钥发送到服务器。我需要将数据作为字节流读取。 我好像没找到办法。

BIO *memBio = BIO_new(BIO_s_mem());

ASN1_PCTX *asn1=ASN1_PCTX_new();//useless unless I know how to use it

BIO_set_flags(memBio, BIO_FLAGS_WRITE);
int ret=EVP_PKEY_print_private(memBio,rsaAppKeys,0, asn1 );

BUF_MEM *bptr;
BIO_get_mem_ptr(memBio, &bptr);
BIO_set_close(memBio, BIO_NOCLOSE); /* So BIO_free() leaves BUF_MEM alone */
BIO_free(memBio);

它以 DER 格式在内存中打印密钥,十六进制字节格式化为字符串,每个字节之间有“:”,还有一个标题。我可以解析它,但我认为必须有更好的方法。 在文档中写道,通过使用 ASN1_PCTX 我可以微调输出,但我找不到任何文档。

知道将密钥作为原始字节获取的简单方法吗? 谢谢

【问题讨论】:

    标签: c++ c openssl rsa


    【解决方案1】:

    好吧..我等不及了,所以我设计了一个肮脏的黑客:

    • 首先我生成一个 PEM 格式的密钥
    • 然后对其进行解析以提取 ASN.1 结构
    • 然后从 ASN.1 结构中提取 2048 位密钥

    至少可以说,ASN.1 解析是脏的。欢迎提出建议

    我还使用了出色的 http://lapo.it/asn1js/ 来探索 ASN.1 结构。 和https://shanetully.com/2012/04/simple-public-key-encryption-with-rsa-and-openssl/ 尝试以base64 格式打印键。

    //generic method to extract data from an EVP_PKEY
    //it's very UGLY. I'm ashamed especially of the ASN.1 parsing (!!)
    -(NSData *)getPublicKeyBytes:(EVP_PKEY *)rsaKey{
        ///try to write bytes
        BIO *pub = BIO_new(BIO_s_mem());
    
        //write pub key as this format:
        //-----BEGIN RSA PUBLIC KEY-----
        //MIIBCgKCAQEA3J7MfnosapxZH9ibxm9Gz88X+ryEEk616BtXGFx3SH1T7ssjdTvv
        //pL8FRAvnmHegtNm0JsCFbEWdGzFr1F7BFYu1lj6h7JFPIhlalMMSlGsRP5dzzj8q
        //....
        //-----END RSA PUBLIC KEY-----
        //
        PEM_write_bio_RSAPublicKey(pub, rsaKey->pkey.rsa);
    
        size_t pub_len = BIO_pending(pub);
    
        char *pub_key = malloc(pub_len + 1);
    
        BIO_read(pub, pub_key, pub_len);
        //zero terminated string
        pub_key[pub_len] = '\0';
    
        //transform to nsstring
        NSString *plainKey=[[NSString alloc]initWithCString:pub_key encoding:NSASCIIStringEncoding];
        //search for header
        NSRange range=[plainKey rangeOfString:@"-----BEGIN RSA PUBLIC KEY-----"];
        if(range.location==NSNotFound){
            DLog(@"Error, RSA pub key in wrong format: %@",plainKey);
            return nil;
        }
        //strip header
        plainKey=[plainKey substringFromIndex:range.location+range.length];
    
        //search footer
        range=[plainKey rangeOfString:@"-----END RSA PUBLIC KEY-----"];
        if(range.location==NSNotFound){
            DLog(@"Error, RSA pub key in wrong format: %@",plainKey);
            return nil;
        }
    
        //strip footer
        plainKey=[plainKey substringToIndex:range.location];
    
        //now remove \n
        plainKey=[plainKey stringByReplacingOccurrencesOfString:@"\n" withString:@""];
        plainKey=[plainKey stringByReplacingOccurrencesOfString:@"\r" withString:@""];
        //DLog(@"Plain key stripped %@",plainKey);
    
        //now read as byte
        NSData *rsaBytes=[NSData dataWithBase64EncodedString:plainKey];
        //DLog(@"Data is %d len %@",rsaBytes.length,rsaBytes);
        //unfortunately data is in a ASN1 rame;;
        //it's a sequence of 2 element, integer and exponent (65537).
        //the key starts from byte 9, or 10.. (byte 9 is a zero).
        NSData *pubKeyBytes=[rsaBytes subdataWithRange:NSMakeRange(9, 256)];
        DLog(@"pubKeyBytes is %d len %@",pubKeyBytes.length,pubKeyBytes);
    
        return pubKeyBytes;
    }
    

    【讨论】:

      【解决方案2】:

      使用 d2i_RSA_PUBKEY() 从 der 编码的字节流创建 RSA 公钥

      然后使用BN_bn2bin() 函数将 RSA 公钥模数转换为大端字节流。

      例如。

      RSA * pubKey = d2i_RSA_PUBKEY(NULL, <der encoded byte stream pointer>, <num bytes>);
      BN_bn2bin(pubKey->n, <where to put the result>);
      

      【讨论】:

        猜你喜欢
        • 2018-01-27
        • 2014-01-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-16
        • 2017-02-06
        • 2017-07-08
        相关资源
        最近更新 更多