如何将pem公钥转换为openssl RSA *结构

假设我必须像这样公开pem键

-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7vbqajDw4o6gJy8UtmIbkcpnk O3Kwc4qsEnSZp/TR+fQi62F79RHWmwKOtFmwteURgLbj7D/WGuNLGOfa/2vse3G2 eHnHl5CB8ruRX9fBl/KgwCVr2JaEuUm66bBQeP5XeBotdR4cvX38uPYivCDdPjJ1 QWPdspTBKcxeFbccDwIDAQAB -----END PUBLIC KEY----- 

我想使用openssl

int RSA_public_decrypt(int flen, const unsigned char *from, unsigned char *to,RSA *rsa, int padding) 。 如何将pem键转换为RSA *rsa结构?

仅供参考:我不能使用BIO,因为我只想将openssl移植到没有UNIX文件系统的引导加载程序中。 我能做的唯一方法是将公钥转换为C数组。

我不能使用BIO,因为我只想将openssl移植到没有UNIX文件系统的bootloader中

我认为您仍然可以使用BIO ,它只需要是内存BIO ,而不是文件BIO

如果您也不能使用内存BIO ,那么我不确定您是否可以在此处使用OpenSSL。


如何将pem公钥转换为openssl RSA *结构

使用PEM_read_PUBKEYPEM_read_bio_PUBKEY (或其中一个*_PUBKEY例程)。 他们返回EVP_PKEY 。 然后,使用EVP_PKEY_get1_RSA将其转换为RSA

就像是:

 static const char key[] = "-----BEGIN PUBLIC KEY-----\n" "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7vbqajDw4o6gJy8UtmIbkcpnk\n" "O3Kwc4qsEnSZp/TR+fQi62F79RHWmwKOtFmwteURgLbj7D/WGuNLGOfa/2vse3G2\n" "eHnHl5CB8ruRX9fBl/KgwCVr2JaEuUm66bBQeP5XeBotdR4cvX38uPYivCDdPjJ1\n" "QWPdspTBKcxeFbccDwIDAQAB\n" "-----END PUBLIC KEY-----\n"; BIO* bio = BIO_new_mem_buf(key, (int)sizeof(key)); ASSERT(bio != NULL); EVP_PKEY* pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); ASSERT(pkey != NULL); int type = EVP_PKEY_get_type(pkey); ASSERT(type == EVP_PKEY_RSA || type == EVP_PKEY_RSA2); RSA* rsa = EVP_PKEY_get1_RSA(pkey); ASSERT(rsa != NULL); ... EVP_PKEY_free(pkey); RSA_free(rsa); BIO_free(bio); 

这是你需要的助手。 EVP_PKEY_get_type不是库的一部分:

 int EVP_PKEY_get_type(EVP_PKEY *pkey) { ASSERT(pkey); if (!pkey) return EVP_PKEY_NONE; return EVP_PKEY_type(pkey->type); } 

相关的,您还可以使用非PEM版本,即密钥的ASN.1 / DER编码。 这样可以在图像中保存一些尺寸。 然后,您将使用d2i_PUBKEY_bio来读取密钥。

从PEM转换为ASN.1 / DER将节省大约110个字节:

 $ ls -al pubkey.* -rw-r--r-- 1 user staff 162 Jun 5 00:36 pubkey.der -rw-r--r-- 1 user staff 272 Jun 5 00:52 pubkey.pem 

若要将PEM编码的公钥转换为ASN.1 / DER,请按照下列步骤操作。 首先,将密钥复制到剪贴板。 其次,使用OS X上的xclip或Linux上的pbpaste等工具将其导入openssl pkey xclip

 $ pbpaste | openssl pkey -pubin -inform PEM -out pubkey.der -outform DER 

然后,检查公钥:

  $ dumpasn1 pubkey.der 0 159: SEQUENCE { 3 13: SEQUENCE { 5 9: OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1) 16 0: NULL : } 18 141: BIT STRING, encapsulates { 22 137: SEQUENCE { 25 129: INTEGER : 00 BB BD BA 9A 8C 3C 38 A3 A8 09 CB C5 2D 98 86 : E4 72 99 E4 3B 72 B0 73 8A AC 12 74 99 A7 F4 D1 : F9 F4 22 EB 61 7B F5 11 D6 9B 02 8E B4 59 B0 B5 : E5 11 80 B6 E3 EC 3F D6 1A E3 4B 18 E7 DA FF 6B : EC 7B 71 B6 78 79 C7 97 90 81 F2 BB 91 5F D7 C1 : 97 F2 A0 C0 25 6B D8 96 84 B9 49 BA E9 B0 50 78 : FE 57 78 1A 2D 75 1E 1C BD 7D FC B8 F6 22 BC 20 : DD 3E 32 75 41 63 DD B2 94 C1 29 CC 5E 15 B7 1C : 0F 157 3: INTEGER 65537 : } : } : } 

最后,做一些事情:

 int main(int argc, char* argv[]) { UNUSED(argc), UNUSED(argv); static const unsigned char key[] = { 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0xbd, 0xba, 0x9a, 0x8c, 0x3c, 0x38, 0xa3, 0xa8, 0x09, 0xcb, 0xc5, 0x2d, 0x98, 0x86, 0xe4, 0x72, 0x99, 0xe4, 0x3b, 0x72, 0xb0, 0x73, 0x8a, 0xac, 0x12, 0x74, 0x99, 0xa7, 0xf4, 0xd1, 0xf9, 0xf4, 0x22, 0xeb, 0x61, 0x7b, 0xf5, 0x11, 0xd6, 0x9b, 0x02, 0x8e, 0xb4, 0x59, 0xb0, 0xb5, 0xe5, 0x11, 0x80, 0xb6, 0xe3, 0xec, 0x3f, 0xd6, 0x1a, 0xe3, 0x4b, 0x18, 0xe7, 0xda, 0xff, 0x6b, 0xec, 0x7b, 0x71, 0xb6, 0x78, 0x79, 0xc7, 0x97, 0x90, 0x81, 0xf2, 0xbb, 0x91, 0x5f, 0xd7, 0xc1, 0x97, 0xf2, 0xa0, 0xc0, 0x25, 0x6b, 0xd8, 0x96, 0x84, 0xb9, 0x49, 0xba, 0xe9, 0xb0, 0x50, 0x78, 0xfe, 0x57, 0x78, 0x1a, 0x2d, 0x75, 0x1e, 0x1c, 0xbd, 0x7d, 0xfc, 0xb8, 0xf6, 0x22, 0xbc, 0x20, 0xdd, 0x3e, 0x32, 0x75, 0x41, 0x63, 0xdd, 0xb2, 0x94, 0xc1, 0x29, 0xcc, 0x5e, 0x15, 0xb7, 0x1c, 0x0f, 0x02, 0x03, 0x01, 0x00, 0x01 }; BIO* bio = BIO_new_mem_buf(key, (int)sizeof(key)); ASSERT(bio != NULL); EVP_PKEY* pkey = d2i_PUBKEY_bio(bio, NULL); ASSERT(pkey != NULL); int type = EVP_PKEY_get_type(pkey); ASSERT(type == EVP_PKEY_RSA || type == EVP_PKEY_RSA2); RSA* rsa = EVP_PKEY_get1_RSA(pkey); ASSERT(rsa != NULL); // ... EVP_PKEY_free(pkey); RSA_free(rsa); BIO_free(bio); return 0; } 

从pem文件加载RSA pub密钥

 int loadKey(string &fileName, RSA ** pubkey) { FILE *fp = fopen(fileName.data(), "r"); if (fp < 0){ printf("%s\n","Invalide certificate file name"); return -1; } *pubkey = PEM_read_RSA_PUBKEY(fp,pubkey, NULL, NULL); if(*pubkey == NULL){ printf("%s\n","error reading Public key"); return -1; } 

validation签名

 int verify_signature(vector &msg, vector &sig, RSA* pkey) { /* Returned to caller */ int result = -1; vector  pDecrypted(PACKAGE_SIGNATURE_SIZE); result = RSA_public_decrypt(PACKAGE_SIGNATURE_SIZE, sig.data(), pDecrypted.data(), pkey, RSA_NO_PADDING); if (result == -1) { printf("RSA_public_decrypt failed with error %s\n", ERR_error_string(ERR_get_error(), NULL)); // goto prog_end; } /* verify the data */ result = RSA_verify_PKCS1_PSS(pkey,msg.data() , EVP_sha256(), pDecrypted.data(), -2 /* salt length recovered from signature*/); if (result == 1) { printf("Signature verification successfull!\n"); } else { printf("RSA_verify_PKCS1_PSS failed with error %s\n", ERR_error_string(ERR_get_error(), NULL)); } return !!result; }