openssl生成公钥私钥对的方法
在计算机软件开发世界中,编程语言种类极多,数据在各种语言的表现形式可能有所差异,但数据本身的处理可能,或者说本质上是完全一样的;比如数据在某个算法中的运算过程是一样的。在这里,我以加密与解密来作为例子说明。
在C++下,我使用OPENSSL库生成了RSA的公私钥对与DES加密之用的会话密钥,并将这三者及加密结果写入文件以备在Java环境下使用。
在C++程序中,我使用使用公钥来加密了DES的会话密钥,然后在Java下使用私钥来解密会话密钥;在运算结果中,我未做其它方面的码制转换,即按密钥的初始格式DER编码,数学运算结果也是按DER编码来实现。
在Java程序中,我从之前所存储的几个文件中取得密钥与加密结果来做解密。我使用了BC的JCE,即bcprov-jdk14-119.jar,在使用之前,需要先安装此JCE:
假设JDK:jdk1.4\jre\
把BC包放到JRE下的ext:jdk1.4\jre\lib\ext
修改文件jdk1.4\jre\lib\security\java.security:
#
#Listofprovidersandtheirpreferenceorders(seeabove):
#
security.provider.1=sun.security.provider.Sun
security.provider.2=com.sun.net.ssl.internal.ssl.Provider
security.provider.3=com.sun.rsajca.Provider
security.provider.4=com.sun.crypto.provider.SunJCE
security.provider.5=sun.security.jgss.SunProvider
security.provider.6=org.bouncycastle.jce.provider.BouncyCastleProvider
======================================================================
C++程序源码:
#include
#include
#include
//#define_RSA_KEY_PAIR_GENERATE_//密钥是否要生成只需要在第一次运行时打开此宏
#define_RSA_KEY_PAIR_TOFILE_//密钥对是否要写入文件
#defineMAX_RSA_KEY_LENGTH512//密钥的最大长度是512字节
#definePUBKEY_ENCRYPT
#definePRIKEY_DECRYPT
#pragmacomment(lib,"../lib/libeay32.lib")
staticconstchar*PUBLIC_KEY_FILE="pubkey.key";
staticconstchar*PRIVATE_KEY_FILE="prikey.key";
intRsaKeyPairGen(void)
{
RSA*rsa=NULL;
#ifdef_RSA_KEY_PAIR_GENERATE_
//生成RSA密钥对:
rsa=RSA_new();
rsa=RSA_generate_key(1024,0x10001,NULL,NULL);
#endif
//把密钥对写入文件,以后从文件里读取
#ifdef_RSA_KEY_PAIR_TOFILE_
unsignedcharucPubKey[MAX_RSA_KEY_LENGTH]={0},ucPriKey[MAX_RSA_KEY_LENGTH]={0};
intlen=i2d_RSAPublicKey(rsa,NULL);
unsignedchar*pt=ucPubKey;
len=i2d_RSAPublicKey(rsa,&pt);
FILE*fpubkey=NULL;
fpubkey=fopen(PUBLIC_KEY_FILE,"wb");
if(fpubkey==NULL)
{
cout<<"fopenpubkey.keyfailed!"<<endl;
return0x01;
}
fwrite(ucPubKey,1,len,fpubkey);
fclose(fpubkey);
len=i2d_RSAPrivateKey(rsa,NULL);
unsignedchar*pt2=ucPriKey;
len=i2d_RSAPrivateKey(rsa,&pt2);
FILE*fprikey=NULL;
fprikey=fopen(PRIVATE_KEY_FILE,"wb");
if(fprikey==NULL)
{
cout<<"fopenprikey.keyfailed!"<<endl;
return0x02;
}
fwrite(ucPriKey,1,len,fprikey);
fclose(fprikey);
#endif
if(rsa!=NULL)
{
RSA_free(rsa);
rsa=NULL;
}
return0;
}
//从文件里读取私钥的数据,取得RSA格式的私钥:
intGetPriKey(unsignedchar*pucPriKeyData,unsignedlongKeyDataLen,RSA**priRsa)
{
unsignedchar*Pt=pucPriKeyData;
*priRsa=d2i_RSAPrivateKey(NULL,&Pt,KeyDataLen);
if(priRsa==NULL)
{
cout<<"priRsa==NULL!"<<endl;
return0x22;
}
return0;
}
//取得RSA格式的公钥:
intGetPubKey(unsignedchar*pucPubKeyData,unsignedlongKeyDataLen,RSA**pubRsa)
{
unsignedchar*Pt=pucPubKeyData;
*pubRsa=d2i_RSAPublicKey(NULL,&Pt,KeyDataLen);
if(pubRsa==NULL)
{
cout<<"pubRsa==NULL!"<<endl;
return0x31;
}
return0;
}
//公钥加密会话密钥:
intencSessionKeybyRsaPubKey(RSA*rsa,unsignedchar*ucKey,unsignedlongulKeyLen,
unsignedchar*outData,unsignedlong*pulOutLen)
{
return(*pulOutLen=RSA_public_encrypt(ulKeyLen,ucKey,outData,rsa,1));
}
//私钥解密会话密钥:
intdecSessionKeybyRsaPriKey(RSA*rsa,unsignedchar*InData,unsignedlongulDataLen,
unsignedchar*ucKey,unsignedlong*pulKeyLen)
{
return(*pulKeyLen=RSA_private_decrypt(ulDataLen,InData,ucKey,rsa,1));
}
intmain(intargc,char*argv[])
{
unsignedcharucKey[8]={0x01,0x03,0x99,0x4,\
0x80,0x65,0x34,0x08};
unsignedcharucEncryptedKey[512]={0},ucDecryptedKey[512]={0};
unsignedlongencrypted_len=0,decrypted_len=0;
#ifdef_RSA_KEY_PAIR_GENERATE_
RsaKeyPairGen();
#endif
//取得公钥:
unsignedcharucPubKey[MAX_RSA_KEY_LENGTH]={0};
FILE*fpubkey=NULL;
fpubkey=fopen(PUBLIC_KEY_FILE,"rb");
if(fpubkey==NULL)
{
cout<<"fopenpubkey.keyfailed!"<<endl;
return0x03;
}
fseek(fpubkey,0,SEEK_END);
intlen_PK=ftell(fpubkey);
fseek(fpubkey,0,SEEK_SET);
fread(ucPubKey,1,len_PK,fpubkey);
fclose(fpubkey);
#ifdefPUBKEY_ENCRYPT
RSA*pRsaPubKey=NULL;
pRsaPubKey=RSA_new();
GetPubKey(ucPubKey,len_PK,&pRsaPubKey);
//公钥加密:
encSessionKeybyRsaPubKey(pRsaPubKey,ucKey,sizeof(ucKey),ucEncryptedKey,&encrypted_len);
//writetofile:
FILE*fp=NULL;
fp=fopen("ucKey.data","wb");
fwrite(ucEncryptedKey,1,encrypted_len,fp);
fclose(fp);
if(pRsaPubKey!=NULL)
{
RSA_free(pRsaPubKey);pRsaPubKey=NULL;
}
#endif
//取得私钥:
unsignedcharucPriKey[MAX_RSA_KEY_LENGTH]={0};
FILE*fprikey=NULL;
fprikey=fopen(PRIVATE_KEY_FILE,"rb");
if(fprikey==NULL)
{
cout<<"fopenprikey.keyfailed!"<<endl;
return0x02;
}
fseek(fprikey,0,SEEK_END);
intlen_SK=ftell(fprikey);
fseek(fprikey,0,SEEK_SET);
fread(ucPriKey,1,len_SK,fprikey);
fclose(fprikey);
#ifdefPRIKEY_DECRYPT
RSA*pRsaPriKey=NULL;
pRsaPriKey=RSA_new();
GetPriKey(ucPriKey,len_SK,&pRsaPriKey);
//私钥解密:
FILE*fp1=NULL;
fp1=fopen("ucKey.data","rb");
intlen=ftell(fp1);
fseek(fp1,0,SEEK_SET);
fread(ucPriKey,1,len_SK,fp1);
fclose(fp1);
decSessionKeybyRsaPriKey(pRsaPriKey,ucEncryptedKey,encrypted_len,ucDecryptedKey,&decrypted_len);
if(pRsaPriKey!=NULL)
{
RSA_free(pRsaPriKey);pRsaPriKey=NULL;
}
//数据对比:
if(0==memcmp(ucKey,ucDecryptedKey,decrypted_len))
{
cout<<"OK!"<<endl;
}
else
{
cout<<"FAILED!"<<endl;
}
#endif
return0;
}
======================================================================
Java程序源码:
======================================================================
packagejrsaencrypt;
importjava.io.*;
importjava.security.*;
importjava.security.spec.*;
importjava.security.PublicKey;
importjava.security.PrivateKey;
importjava.security.KeyFactory;
importjavax.crypto.Cipher.*;
/**
*
Title:
*
Description:
*
Copyright:Copyright(c)2005
*
Company:
*@authornotattributable
*@version1.0
*/
publicclassRsaKeyGen{
publicRsaKeyGen(){
}
/**
*生成RSA密钥对
*@return
*/
intgenerateRsaKeyPair(){
//generateanRSAkeypair
try{
KeyPairGeneratorkeyGen=KeyPairGenerator.getInstance("RSA");
keyGen.initialize(1024);
KeyPairpair=keyGen.generateKeyPair();
System.out.println(pair.getPublic().getFormat());
System.out.println(pair.getPublic().getAlgorithm());
System.out.println("\nRSApublicKey:");
byte[]bPubKey=pair.getPublic().getEncoded();
System.out.println(bPubKey.length);
for(inti=0;i<bPubKey.length;i++){
System.out.print(bPubKey[i]+"");
}
System.out.println("\nRSAprivateKey:");
byte[]bPriKey=pair.getPrivate().getEncoded();
System.out.println(bPriKey.length);
for(inti=0;i<bPriKey.length;i++){
System.out.print(bPriKey[i]+"");
}
}
catch(Exceptione){
e.printStackTrace();
}
return0;
}
/**
*从公钥数据取得公钥
*@parambPubKeyInput
*@return
*/
PublicKeygetRsaPubKey(byte[]bPubKeyInput){
byte[]bX509PubKeyHeader={
48,-127,-97,48,13,6,9,42,-122,72,-122,-9,13,1,1,1,5,0,
3,-127,-115,0};
try{
byte[]bPubKey=newbyte[bPubKeyInput.length+bX509PubKeyHeader.length];
System.arraycopy(bX509PubKeyHeader,0,bPubKey,0,
bX509PubKeyHeader.length);
System.arraycopy(bPubKeyInput,0,bPubKey,bX509PubKeyHeader.length,
bPubKeyInput.length);
X509EncodedKeySpecrsaKeySpec=newX509EncodedKeySpec(bPubKey);
KeyFactorykeyFactory=KeyFactory.getInstance("RSA");
rsaPubKey=keyFactory.generatePublic(rsaKeySpec);
}
catch(Exceptione){
e.printStackTrace();
}
returnrsaPubKey;
}
/**
*从私钥数据取得私钥
*@parambPriKeyInput
*@return
*/
PrivateKeygetRsaPriKey(byte[]bPriKeyInput){
byte[]bX509PriKeyHeader={
48,-126,2,117,2,1,0,48,13,6,9,42,
-122,72,-122,-9,13,1,1,1,5,0,4,-126,2,95};
try{
byte[]bPriKey=newbyte[bX509PriKeyHeader.length+bPriKeyInput.length];
System.arraycopy(bX509PriKeyHeader,0,bPriKey,0,
bX509PriKeyHeader.length);
System.arraycopy(bPriKeyInput,0,bPriKey,bX509PriKeyHeader.length,
bPriKeyInput.length);
PKCS8EncodedKeySpecrsaKeySpec=newPKCS8EncodedKeySpec(bPriKey);
KeyFactorykeyFactory=KeyFactory.getInstance("RSA");
rsaPriKey=keyFactory.generatePrivate(rsaKeySpec);
}
catch(Exceptione){
e.printStackTrace();
}
returnrsaPriKey;
}
/**
*从文件里取得数据
*@paramstrFileName
*@parambFBytes
*@return
*/
intgetBytesbyFileName(StringstrFileName,byte[]bFBytes){
intfSize=0;
try{
FileInputStreamfIn=newFileInputStream(strFileName);
fSize=fIn.available();
System.out.print("file'ssize:");
System.out.println(fSize);
fSize=fIn.read(bFBytes);
fIn.close();
}
catch(Exceptione){
e.printStackTrace();
}
returnfSize;
}
/**
*公钥加密
*@parambKey
*@return
*/
byte[]rsaPubKeyEncrypt(byte[]bKey){
try{
//Providerprvd=Security.getProvider("BouncyCastle");
javax.crypto.CipherrsaPKenc=javax.crypto.Cipher.getInstance(
"RSA/ECB/PKCS1Padding");
rsaPKenc.init(javax.crypto.Cipher.ENCRYPT_MODE,rsaPubKey);
bEncryptedData=rsaPKenc.doFinal(bKey);
}
catch(Exceptione){
e.printStackTrace();
}
returnbEncryptedData;
}
/**
*私钥解密
*@parambEncryptedKey
*@return
*/
byte[]rsaPriKeyDecrypt(byte[]bEncryptedKey){
try{
javax.crypto.CipherrsaSKDec=javax.crypto.Cipher.getInstance(
"RSA/ECB/PKCS1Padding");
rsaSKDec.init(javax.crypto.Cipher.DECRYPT_MODE,rsaPriKey);
byte[]bDecrypt=rsaSKDec.doFinal(bEncryptedKey);
//System.out.println("rsadecryptedresult[beforeclean]:");
//for(inti=0;i<bDecrypt.length;i++){
//System.out.print(bDecrypt[i]+"");
//}
//System.out.println();
inti=0;
//for(i=bDecrypt.length;i>1;i--){
//if(bDecrypt[i-1]==0){
//System.out.println("i="+i);
//break;
//}
//}//for
bDecryptedData=newbyte[bDecrypt.length-i];
System.arraycopy(bDecrypt,i,bDecryptedData,0,bDecrypt.length-i);
}
catch(Exceptione){
e.printStackTrace();
}
returnbDecryptedData;
}
publicstaticvoidmain(String[]args){
RsaKeyGenrsaKeyGen1=newRsaKeyGen();
//rsaKeyGen1.generateRsaKeyPair();
//byte[]bPubKey=newbyte[140];
//intlen=rsaKeyGen1.getBytesbyFileName("pubkey.key",bPubKey);
//rsaKeyGen1.getRsaPubKey(bPubKey);
byte[]bPriKey=newbyte[607];
intlen2=rsaKeyGen1.getBytesbyFileName("prikey.key",bPriKey);
rsaKeyGen1.getRsaPriKey(bPriKey);
//byte[]bKey={
//1,2,3,4,5,6,7,8};
////encrypt:
//byte[]bEncKey=rsaKeyGen1.rsaPubKeyEncrypt(bKey);
//System.out.println("rsaencryptedresult:");
//for(inti=0;i<bEncKey.length;i++){
//System.out.print(bEncKey[i]+"");
//}
//System.out.println();
byte[]bEncKey=newbyte[128];
intlen0=rsaKeyGen1.getBytesbyFileName("ucKey.data",bEncKey);
byte[]bDecKey=rsaKeyGen1.rsaPriKeyDecrypt(bEncKey);
System.out.println("rsadecryptedresult:");
for(inti=0;i<bDecKey.length;i++){
System.out.print(bDecKey[i]+"");
}
System.out.println();
}
PublicKeyrsaPubKey;
PrivateKeyrsaPriKey;
byte[]bEncryptedData;
byte[]bDecryptedData;
}