使用openssl以编程方式将rs。私钥从.DER格式转换为.PEM格式

时间:2012-10-25 10:53:15

标签: cryptography openssl key rsa

如何使用openssl api以编程方式将rsa私钥从.DER格式转换为.PEM格式。手动我可以使用openssl exe进行转换。请以编程方式建议如何执行此操作。

1 个答案:

答案 0 :(得分:3)

C OpenSSL API中有一些名称为i2d_*的函数,用于解析内部类型(对于c编程语言是名为X509,RSA的结构...)到DER和d2i_*来解析DER为内部类型,这就是如何使用c编程语言将x509证书文件从DER格式转换为PEM。

#include <stdio.h>
#include <openssl/x509.h>

int main(int argc,char* argv[]){
    if(argc != 3) {
        printf("Usage: der2pem derfile pemfile\n");
        return 1;
    }
    // try open the derfile
    FILE* derfile = fopen(argv[1],"r");
    if(derfile) {
        // try open or create the pemfile
        FILE* pemfile = fopen(argv[2],"w+");
        if(pemfile) {
            // parse DER to internal X509 structure
            // d2i is d for DER and i for internal which means c data
            X509* internal = d2i_X509_fp(derfile,NULL);
            if(internal) {
                // write from the internal X509 to pemfile
                PEM_write_X509(pemfile,internal);
            }
            else {
                printf("wasn't possible to parse to X509 from the 'derfile'\n");
            }
            fclose(pemfile);
        }
        else {
            printf("can't create or open the 'pemfile' file\n");
            return 1;
        }
        fclose(derfile);
    }
    else {
        printf("can't open the 'derfile' file\n");
        return 1;
    }
    return 0;
}

X.509数字证书是一种数据结构,至少包含以下字段:

  • 公钥所有者的可分辨名称,也称为 主题名称
  • 证书颁发者的专有名称,也称为 发行人的名字
  • 公钥本身
  • 证书有效的时间段,也称为 有效期
  • 发行人指定的证书序列号
  • 发行人的数字签名。

来源http://publib.boulder.ibm.com/infocenter/zos/v1r11/index.jsp?topic=/com.ibm.zos.r11.icha700/xcerts.htm

这意味着此示例不适用于任何类型的私钥,证书请求,证书吊销列表。如果您需要从这些类型的DER文件转换,您必须更多地深入OpenSSL API,因为例如私钥与加密和解密有关。

@owlstead说道,这是真的...... PEM格式是DER格式的base64编码加上页眉和页脚。然后我在c中再写了一个例子,但你需要知道正确的页眉和页脚来创建一个完整的PEM文件:

#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <openssl/bio.h>
#include <openssl/evp.h>

int main(int argc,char* argv[]){
    if(argc != 5) {
        printf("Usage: der2pem_simple derfile pemfile \"-----BEGIN CERTIFICATE-----\" \"-----END CERTIFICATE-----\"\n");
        return 1;
    }
    // to create a buffer as small as possible
    // we need the size of the input file
    struct stat fistat;
    if(stat(argv[1],&fistat)<0) {
        printf("derfile not found\n");
        return 1;
    }
    // open the derfile
    FILE* derfile = fopen(argv[1],"r");
    if (!derfile){
        printf("can't open derfile\n");
        return 1;
    }
    char buff[fistat.st_size];
    // write the derfile to the buffer
    fread(buff,fistat.st_size,1,derfile);
    fclose(derfile);
    // open pemfile
    FILE* pemfile = fopen(argv[2],"w+");
    if (!pemfile){
        printf("can't open or create pemfile\n");
        return 1;
    }
    // create a BIO context with base64 filter
    BIO* bio_base64 = BIO_new(BIO_f_base64());
    // create a BIO for the pemfile
    BIO* bio_out = BIO_new_fp(pemfile,BIO_NOCLOSE);
    // write the header
    BIO_write(bio_out,argv[3],strlen(argv[3]));
    BIO_write(bio_out,"\n",1);
    // combine bio_base64->bio_out : enables base64 filter
    bio_out = BIO_push(bio_base64,bio_out);
    // write the buffer
    BIO_write(bio_out,buff,fistat.st_size);
    // flush before disable base64 filter
    BIO_flush(bio_out);
    // uncombine bio_base64 X bio_out : disables base64 filter
    bio_out = BIO_pop(bio_base64);
    // write the footer
    BIO_write(bio_out,argv[4],strlen(argv[4]));
    // flush to free the BIO resources
    BIO_flush(bio_out);
    BIO_free_all(bio_out);
    fclose(pemfile);
}

以及Java中的这个例子:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.apache.commons.codec.binary.Base64;
//import org.apache.commons.codec.binary.Base64OutputStream;

public class der2pem {
    public static void main(String args[]) {
        if(args.length < 4) {
            System.out.println("Usage: der2pem_simple derfile pemfile \"-----BEGIN CERTIFICATE-----\" \"-----END CERTIFICATE-----\"");
            return;
        }
        FileOutputStream pemfile;
        try {
            // open the pemfile
            pemfile = new FileOutputStream(args[1]);
        } catch (FileNotFoundException e) {
            try {
                // try to create if not found
                new File(args[1]).createNewFile();
            } catch (IOException e1) {
                System.out.println(e1.getMessage());
                return;
            }
            try {
                // if created open it
                pemfile = new FileOutputStream(args[1]);
            } catch (FileNotFoundException e1) {
                e1.printStackTrace();
                return;
            }
        }
        FileInputStream derfile;
        try {
            // open the derfile
            derfile = new FileInputStream(args[0]);
        } catch (FileNotFoundException e) {
            // if not found print error and get out
            System.out.println(e.getMessage());
            try {
                pemfile.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            return;
        }
        try {
//---- last part
        // write the header to pemfile
        pemfile.write(args[2].getBytes());
        pemfile.write('\n');
        // get the size of the derfile and create a buff that fits to this file
        int derf_size = (int) new File(args[0]).length();
        byte[] buffer = new byte[derf_size];
        // read from derfile and write to buffer
        derfile.read(buffer);
        // create the Base64 object for the encoding
        Base64 base64 = new Base64(64,"\n".getBytes());
        // encode and write to pemfile
        pemfile.write(base64.encode(buffer));
        // write the footer to pemfile
        pemfile.write(args[3].getBytes());
        // flush to cleanup
        pemfile.flush();
        pemfile.close();
        derfile.close();
//---- last part end
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

我尝试使用Base64OutputStream的方法,但在PEM文件上有一些意外的结果。如果您想检查,只需将last part替换为:

        // write the header to pemfile
        pemfile.write(args[2].getBytes());
        pemfile.write('\n');
        // get the size of the derfile and create a buff that fits to this file
        int derf_size = (int) new File(args[0]).length();
        byte[] buffer = new byte[derf_size];
        // read from derfile and write to buffer
        derfile.read(buffer);
        // create the Base64OutputStream object for the encoding
        Base64OutputStream b64f_pemfile = new Base64OutputStream(pemfile,true,64,"\n".getBytes());
        // write to b64f_pemfile which encodes to base64
        b64f_pemfile.write(buffer);
        // flush before write the footer
        b64f_pemfile.flush();
        // write the footer
        pemfile.write('\n'); 
        pemfile.write(args[3].getBytes());
        // flush to cleanup
        pemfile.flush();
        b64f_pemfile.close();
        pemfile.close();
        derfile.close();

我编译它:

javac der2pem.java -classpath "$CLASSPATH:/usr/share/java/commons-codec.jar"

并以:

运行
java -classpath "$CLASSPATH:/usr/share/java/commons-codec.jar" der2pem test.der tttttt "-----BEGIN CERTIFICATE-----" "-----END CERTIFICATE-----"

你需要在你的系统中做类似的事情。