1)示例1
#include <openssl/pem.h>
#include <openssl/evp.h>
int mycb(char *buf,int num,int a,char *key)
{
if(key)
strcpy(buf,key);
else
{
if(a==1)
printf("请输入加密密码:\n");
else
printf("请输入解密密码:\n");
scanf("%s",buf);
}
return strlen(buf);
}
int main()
{
int ret;
BIO *out,*in;
RSA *r,*read;
int i,bits=512;
unsigned long e=RSA_3;
BIGNUM *bne;
const EVP_CIPHER *enc=NULL;
bne=BN_new();
ret=BN_set_word(bne,e);
r=RSA_new();
ret=RSA_generate_key_ex(r,bits,bne,NULL);
if(ret!=1)
{
printf("RSA_generate_key_ex err!\n");
return -1;
}
enc=EVP_des_ede3_ofb();
out=BIO_new_file("pri.pem","w");
// ret=PEM_write_bio_RSAPrivateKey(out,r,enc,NULL,0,mycb,"123456");
// ret=PEM_write_bio_RSAPrivateKey(out,r,enc,NULL,0,NULL,"123456");
ret=PEM_write_bio_RSAPrivateKey(out,r,enc,NULL,0,mycb,NULL);
if(ret!=1)
{
RSA_free(r);
BIO_free(out);
return -1;
}
BIO_flush(out);
BIO_free(out);
out=BIO_new_file("pub.pem","w");
ret=PEM_write_bio_RSAPublicKey(out,r);
if(ret!=1)
{
RSA_free(r);
BIO_free(out);
return -1;
}
BIO_flush(out);
BIO_free(out);
OpenSSL_add_all_algorithms();
in=BIO_new_file("pri.pem","rb");
read=RSA_new();
// read=PEM_read_bio_RSAPublicKey(in,&read,NULL,NULL);
// read=PEM_read_bio_RSAPrivateKey(in,&read,mycb,"123456");
// read=PEM_read_bio_RSAPrivateKey(in,&read,NULL,"123456");
read=PEM_read_bio_RSAPrivateKey(in,&read,mycb,NULL);
if(read->d!=NULL)
printf("test ok!\n");
else
printf("err!\n");
RSA_free(read);
BIO_free(in);
return 0;
}
输出:
请输入加密密码:
123456
请输入解密密码:
123456
test ok!
本示例生成RSA密钥,并将私钥写入成PMI格式写入文件;然后再读取。主要需要注意的是回调函数的用法。用户可以采用默认的方式,也可以自己写。采用默认方式时,回调函数设为NULL,否则设置为用户实现调回调函数地址。另外,最后一个参数如果为空,将需要用户输入口令,否则采用参数所表示的口令。
2)示例2
#include <openssl/pem.h>
#include <openssl/bio.h>
int main()
{
BIO *bp;
char *name=NULL,*header=NULL;
unsigned char*data=NULL;
int len,ret,ret2;
EVP_CIPHER_INFO cipher;
OpenSSL_add_all_algorithms();
bp=BIO_new_file("server2.pem","r");
while(1)
{
ret2=PEM_read_bio(bp,&name,&header,&data,&len);
if(ret2==0)
break;
if(strlen(header)>0)
{
ret=PEM_get_EVP_CIPHER_INFO(header,&cipher);
ret=PEM_do_header(&cipher,data,&len,NULL,NULL);
if(ret==0)
{
printf("PEM_do_header err!\n");
return -1;
}
}
OPENSSL_free(name);
OPENSSL_free(header);
OPENSSL_free(data);
}
printf("test ok.\n");
BIO_free(bp);
return 0;
}
说明:
本例server2.pem的内容如下:
-----BEGIN CERTIFICATE-----
MIIB6TCCAVICAQYwDQYJKoZIhvcNAQEEBQAwWzELMAkGA1UEBhMCQVUxEzARBgNVBAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMRswGQYDVQQDExJUZXN0IENBICgxMDI0IGJpdCkwHhcNMDAxMDE2MjIzMTAzWhcNMDMwMTE0MjIzMTAzWjBjMQswCQYDVQQGEwJBVTETMBEGA1UECBMKUXVlZW5zbGFuZDEaMBgGA1UEChMRQ3J5cHRTb2Z0IFB0eSBMdGQxIzAhBgNVBAMTGlNlcnZlciB0ZXN0IGNlcnQgKDUxMiBiaXQpMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJ+zw4Qnlf8SMVIPFe9GEcStgOY2Ww/dgNdhjeD8ckUJNP5VZkVDTGiXav6ooKXfX3j/7tdkuD8Ey2//Kv7+ue0CAwEAATANBgkqhkiG9w0BAQQFAAOBgQCT0grFQeZaqYb5EYfk20XixZV4GmyAbXMftG1Eo7qGiMhYzRwGNWxEYojf5PZkYZXvSqZ/ZXHXa
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info:
DES-EDE3-CBC,8FDB
CPdURB7aZqM5vgDzZoim/qtoLi5PdrrJol9LrH7CNqJfr9kZfmiexZrE4pV738Hh UBoidqT8moxzDtuBP54FaVri1IJgbuTZPiNbLn00pVcodHdZrrttrjy1eWLlFmN/QcCRQhIoRow+f1AhYGhsOhVH+m4fRb8P9KXpPbEDYVcG0R0EQq6ejdmhS0vV+YXGmghBSGH12i3OfRJXC0TXvazORsT322jiVdEmajND6+DpAtmMmn6JTYm2RKwgFr9vPWv9cRQaMP1yrrBCtMiSINS4mGieN1sE1IvZLhn+/QDNfS4NxgnMfFjSl26TiNd/m29ZNoeDDXEcc6HXhoS/PiT+zPBq7t23hmAroqTVehV9YkFsgr71okOTBwlYMbFJ9goC87HYjJo4t0q9IY53GCuoI1Mont3Wm9I8QlWh2tRq5uraDlSq7U6Z8fwvC2O+wFF+PhRJrgD+4cBETSQJhj7ZVrjJ8cxCbtGcE/QiZTmmyY3sirTlUnIwpKtlfOa9pwBaoL5hKk9ZYa
-----END RSA PRIVATE KEY-----
PEM_read_bio函数可以循环读取文件中的内容。
PEM_do_header用于解密数据,之前必须调用函数OpenSSL_add_all_algorithms。
PEM_do_header解密后的数据放在data中,长度由len表示,len即是输入参数又是输出参数。
name、header和data等用OPENSSL_free释放内存。