第二十二章 PEM格式 / 22.4 编程示例

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/ZXHXa4g59jK/rJNnaVGMk+xIX8mxQvlV0n5O9PIha5BX5teZnkHKgL8aKKLKW1BK7YTngsfSzzaeame5iKfzitAE+OjGF+PFKbwX8Q==

              -----END CERTIFICATE-----

              -----BEGIN RSA PRIVATE KEY-----

              Proc-Type: 4,ENCRYPTED

              DEK-Info: DES-EDE3-CBC,8FDB648C1260EDDA

             

              CPdURB7aZqM5vgDzZoim/qtoLi5PdrrJol9LrH7CNqJfr9kZfmiexZrE4pV738Hh              UBoidqT8moxzDtuBP54FaVri1IJgbuTZPiNbLn00pVcodHdZrrttrjy1eWLlFmN/QcCRQhIoRow+f1AhYGhsOhVH+m4fRb8P9KXpPbEDYVcG0R0EQq6ejdmhS0vV+YXGmghBSGH12i3OfRJXC0TXvazORsT322jiVdEmajND6+DpAtmMmn6JTYm2RKwgFr9vPWv9cRQaMP1yrrBCtMiSINS4mGieN1sE1IvZLhn+/QDNfS4NxgnMfFjSl26TiNd/m29ZNoeDDXEcc6HXhoS/PiT+zPBq7t23hmAroqTVehV9YkFsgr71okOTBwlYMbFJ9goC87HYjJo4t0q9IY53GCuoI1Mont3Wm9I8QlWh2tRq5uraDlSq7U6Z8fwvC2O+wFF+PhRJrgD+4cBETSQJhj7ZVrjJ8cxCbtGcE/QiZTmmyY3sirTlUnIwpKtlfOa9pwBaoL5hKk9ZYa8L1ZCKKMoB6pZw4N9OajVkMUtLiOv3cwIdZk4OIFSSm+pSfcfUdG45a1IQGLoqvt9svckz1sOUhuu5zDPIQUYrHFn3arqUO0zCPVWPMm9oeYOkB2WCz/OiNhTFynyX0r+Hd3XeT26lgFLfnCkZlXiW/UQXqXQFSjC5sWd5XJ1+1ZgAdXq0L5qv/vAIrfryNNZHRFxC8QDDI504OA1AHDkHuH9NO9Ur8U0z7qrsUAf5OnMRUK//QV11En5o/pWcZKD0SVGS03+FVqMhtTsWKzsil5CLAfMbOWUw+/1k1A==

              -----END RSA PRIVATE KEY-----

              PEM_read_bio函数可以循环读取文件中的内容。

              PEM_do_header用于解密数据,之前必须调用函数OpenSSL_add_all_algorithms

              PEM_do_header解密后的数据放在data中,长度由len表示,len即是输入参数又是输出参数。

              nameheaderdata等用OPENSSL_free释放内存。