2013-05-21 152 views
3

我想读取使用Ruby与OpenSSL API生成的AES-128-CBC加密PEM密钥文件。生成的PEM关键代码如下:用OpenSSL C API读取PEM格式的RSA密钥文件

OpenSSL::PKey::RSA.new(2048).to_pem(OpenSSL::Cipher::AES.new('128-CBC'), "password") 

下面是读取PEM文件中的代码:

RSA *rsa; 

BIO *pem = BIO_new(BIO_s_mem()); 
BIO_puts(pem, "-----BEGIN RSA PRIVATE KEY-----\n" 
    "Proc-Type: 4,ENCRYPTED\n" 
    "DEK-Info: AES-128-CBC,BB13D39833DD6ED1FF9843644E7981EE\n\n 
    "Eugt8JZNKQKErsabWkwfm3wQhU/Tmp9T0QaP5HM8VIWpZwKlDmRlSUDptADU6RPD\n" 
    "5VtG3DPieXcf+6deyARImid9sBBmQ9mK2omkNRcTMemqTOhAuaKBu78TMt9G4YSf\n" 
    "RjoXWSqu3jMwrlcGkpn7bIum8wImITRZ3p28oSzk9aDUNBrIU/2Si8DM4RYIZ/fK\n" 
    "Uvvgdok9dgcd0SjvucivX2HaGeg/IUz23q1jg9inDpimZvFJD1FJfGEUWDgyfJfa\n" 
    "M8JIxTKbWOPEopONDkT7u4dC5VcSjK29MVbfd7iCKFPMh5UN+c96rPxTng/OWyW5\n" 
    "0tvzHyyyvAG9p0Hx5Lr4pDbv21GHyu43sA6wbs9jWyqO3AB7CaoEEQhumwfLsdjj\n" 
    "YGrX6bWThpYv/XNBDmmvltHlKFfe01NCybivOb4KwBnvi45x21PBqaZCKDTFdEkL\n" 
    "iwDMTiG2iTxSUvPFLy30VFozE+pGyMcGDUyZDVqjsaqI/MRj8khnn5nyubXc27G3\n" 
    "8Kbsnlix2SW2M0VDxqiy9dyjcxXrkFRSnOFYVs1PFlgjFVTG4Mwh6CZxKw8mFVbi\n" 
    "EmLvUYwzoDZ1ve4VXSPp/vrKEh33JuHhM0vJOpqI6wqw0QR0I2o6etM1ZRJClPcw\n" 
    "VIcgcvwenEgLOkoHDqOr0IZQAtYWvAuqq822wKt258hc6z8+ALQf5iMroqk7ADd4\n" 
    "FlRLz4XTwqlg7pPtTde/emI1DT8dQWzq++QI0lr0CS/N1GXJKqTQDvauXLIiI3Qy\n" 
    "KfFYFpV9jyYfRfTjNtisI/edPtp98auK0mb9o/wS/hruFI9behgv63iW1IwAOXCW\n" 
    "ZlkWgobUH13gS864rL+AcrAXreo2j4dDQouTeRaJUEG0HoYTP65Zun/VsCi2aSOH\n" 
    "JwSnnmHz9OxvcGY80WJDN3kqOCBRIJoDKBv6jcOxGVCsVK+WSdGZ7cfb8lwp7aA8\n" 
    "8ND1bwL9FYkwkeIsoakj91iinqv4o3+3PUPgCU5oe68WYvAFjuU+criyf+EhmXJV\n" 
    "JQ1vFFZPrGzgntJz19uXXh1h2iwQPggRouJm2RozYwvv1nz4eQ40Y3eT1F9UOYJU\n" 
    "CKEhOtI2NpLeVOayqo8g9wO2oC+CQVhZhdYBE5o7pM7akFnYLvRg9s1UsWdcvT0G\n" 
    "IpFmejLSRJ/F954aQMHTUc6vBOJZH/VNC5Qt+ulFXl634Sr9wQQK2qlqSJyA04TR\n" 
    "1ixbCNOX71esvpFImsrlsO5oTA22T3h2GyJPUM10XhqGtDXtsTnal6smLna9U9B3\n" 
    "gTVxFWWukQOF5Lm8ZFQipo2loHWjkozTBc4REPYP44SoXJXstv7k4pt1cK7x6/2H\n" 
    "ElspXzjveqMhcrveWv1KaA2OGd+hGfUiNsCoIdapJjLz1Bd/+oIQ/ZWQeo0nRowE\n" 
    "R/HlbbED3V+fRIdJpgydFEAw6gK5E9sYJcgF7uf/n2NabFxxEZL3g6MJQ64Dtusg\n" 
    "DEH/MpvIYDSX4Navh1gTwCtOeG1CzW3diYaqbZK+UZCBLFU7j27YvVPSd6F2+Wud\n" 
    "WnAqU3S5BCPqk5OD3wqZv+sEcqJgGPGy1Gv0tl8ARJomdKAru03KsRn2eIWqR5/C\n" 
    "-----END RSA PRIVATE KEY-----\n"); 

// Retrieve RSA key from PEM file. 
rsa = PEM_read_bio_RSAPrivateKey(pem, NULL, pem_password_callback, "password"); 

这里是一个虚拟的密码回调(不知道这个功能的目的,但我认为它可能会返回密码的长度):

int pem_password_callback(char *buf, int max_len, int flag, void *pwd) 
{ 
    return 8; 
} 

目前,rsa = ...部分不抛出一个错误,但不会返回任何一个结构良好的结果。

+0

你如何知道这是不正确的? – doptimusprime

+0

在OpenSSL库中似乎没有使用相反的函数。这是在寻找麻烦,特别是因为OpenSSL没有很好的文档记录。例如。它有时使用特定的密钥派生方法。尝试首先匹配加密和解密方法(例如,记录从Ruby调用OpenSSL函数,然后将其反转)。 –

回答

1

这里是一个虚拟的密码回调(不知道这个功能的 目的,但我认为它可能会返回密码的长度):

int pem_password_callback(char *buf, int max_len, int flag, void *pwd) 
{ 
    return 8; 
} 

不,它不是一个假人。在你的例子中,你刚刚返回了一个带有8个垃圾字符的缓冲区(无论发生在buf)。

密码回调是您以编程方式插入密码的地方。您提供的buffmax_len,您需要将密码复制到缓冲区并返回复制的字节数。

int pem_password_callback(char *buf, int max_len, int flag, void *ctx) 
{ 
    const char* PASSWD = "password"; 
    int len = strlen(PASSWD); 

    if(len > max_len) 
     return 0; 

    memcpy(buf, PASSWD, len); 
    return len; 
} 

flag是表示,如果你正在阅读的关键或写入密钥的读/写标志。在实践中,我从来没有使用过它。

您将使用它类似于:

FILE* file = ...; 
EVP_PKEY* pkey = PEM_read_PrivateKey(file, NULL, pem_password_callback, NULL); 

不同的是写程序(这需要一个EVP_*密码),在读出程序知道你用于加密私钥用,因为其编码的关键是什么。

在我的系统中,我实际使用的上下文的标签,以确保相同的密码在不同的派生密钥到达:

EVP_PKEY* pkey = PEM_read_PrivateKey(file, NULL, pem_password_callback, "Some Context"); 

然后,在我的密码回调:

int pem_password_callback(char *buf, int max_len, int flag, void *ctx) 
{ 
    // "Some Context" in the example above 
    char* label = (char*)ctx; 

    // Hash password and label 
    // ... 

    // Copy hash to buffer, return length 
    ... 
} 
相关问题