说明:
1.java生成的公私钥格式为 pkcs8, 而openssl默认生成的公私钥格式为 pkcs1,两者的密钥实际上是不能直接互用的
2.java采用的rsa默认补齐方式是pkcs1, 因此互用的时候需要将openssl中的补齐方式设置为RSA_PKCS1_PADDING采用openssl的rsa算法实现公私钥加解密,这里由于项目需求,公私钥是使用java生成的,因此需要在密钥的首行和最后一行添加标记,两者对比如下:
--------java private key-------(本行不存在)
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAKNQ3j+Ov9THQTMbNw+MwLOGRDwR
qkiH0QffSLBh1Nv6JHBp7yC07b+Nj0lMiBOjoMpk98W3RTdDuRcJ/ojM0OMPZWNiOdvrtJ7I/Haw
DiryMLqWR5gBCC0g+ODs2Cxr1ig5idNaX0bHy9ufSZpFd378OZLBVuOEBtQ7lnFhp/DxAgMBAAEC
gYEAiOBLFPvAHUZOh9XEZPzzuMLMR4gKrrVd5PonguTLsP5KMgknCMN7C3NKZwWEeulF5ruOyh/b
HAFfjEatFNyMKJnUhHwShvvSqncbZMBy9xmaA/FF0BUD285Vb+PhuPnL678KhEcKD3k99A+ym4qW
K9abeiJypAfvnleopBFV+c0CQQDcdUrMdCVCdUIxenIjz67Qp6672iBC2Ni5psow2SZZ9FTC31Z5
7jDowqrvsABbY7XbV8g1LUX/U6JLylXiz7MrAkEAvaU16YtUCdVe4s6saNLnQCfi2ykVdn5ovy3R
ZSn1gzQhy+//GFAhtUTjWO46zBicuNbJ1bNcaiF7DF4evU2OUwJBAJC14WqBlu+f3tpxoLjHG95V
I4qlrOWUR/bdd/1GnTkQ/A6K4c3Zv3saRXBeXG2g7v/TCFV3qWnncTJE18mxQs8CQQCPVxNDvaK8
eADrD2lzJY3SiRNHsWrekDcd4US24RsHm1y8J185gj+oIjRwoEfiweubLgWKN7JvKXU26OD1Fmyv
AkBR63yGMoIMo4AxLnkcr16j9WLBgQ/NXakPHcO2iMtFUsix3SNh96AkxZ+Fs87Ys70RuJOTtA/S
llTOdaKm5PVqpc
--------openssl private key-------(本行不存在)
-----BEGIN RSA PRIVATE KEY-----(存在)
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKIpKYdHzzjEaugD55bBNlV+iJ60
w+C2fecv2ptenw7lUqDRiXTQsMXUiEBPKB5MLtJhLgB9yiph+lIN/lv+7GcPHaEjLwvh0ZnwXiQ2
sbL9sCzvU9r/2otJJ+2NrEf0PA4wEocrSiEv3at7oD3PCVps8nht3fzuPYfCxWhkBXeXAgMBAAEC
gYAm/FZrm6wKLc618RpgeBsj+sPFxBfDkpw6VJrt95Wt8xwmZbnyR6n4JdyL+XvfrNkk4xA4NgXA
osWXrJ2WaHdU/J0C1NnVzwMSISojR3+w5nsY5xyfdhPCNthlWnlmYTXJNOaQUGVO3oR1q0be+drt
uQUV6yvsw/JDftskprqToQJBAOvObGbnz36YgdClJCVHZj3vFDlblAOiOFzIPq0hx72FpYcj/Ho3
3o5bAfZnHPMvOhbMaeY1xpm423f78qV2A+MCQQCwDDWM0uxvTA2XbpQGtVupZbqh/iZQ2eMYp8FJ
t4aa/brUesXZurqsHWcrM6HrWp7gA6DzYeSSy6cCeVV6dlO9AkBaW7JMSH3JO/Valz1fj5mNGAT+
6amxLsM8QntJ6ozYgdLpExAXYTtF/3ekDOUaBrnSrKfT0D13AFARDRlw7+UTAkAO7hokhUbT8Yk9
jH01THAnn58CWgF53eCqmJ+F1vCteFM97eOVoYZvTlcPjONwiFDtAqHFwkmWQXs6dHvRVPOpAkEA
jalQvMpQM7Ej3s2oK386LVrH/La0hZZ6Fn4bgCJ26YxB3AGN5J8uHLjU5oBUMxDefc0OraDdyStJ
pAh2vYzETw==
-----END RSA PRIVATE KEY-----
下面分别用c与java语言实现了将一个字符串转化成对应的公钥与私结构体:
openssl的rsa算法中的公钥与私钥key获取 :
EVP_PKEY* generate_private_key(char *pri_key_data)
{
EVP_PKEY* key = NULL;
RSA *rsa = RSA_new();
OpenSSL_add_all_algorithms();
BIO *bp = NULL;
bp = BIO_new(BIO_s_mem());
BIO_puts(bp, pri_key_data);
rsa = PEM_read_bio_RSAPrivateKey(bp, &rsa, NULL, NULL);
if (rsa == NULL)
{
printf("open_private_key failed to PEM_read_bio_RSAPrivateKey!\n");
BIO_free(bp);
RSA_free(rsa);
return NULL;
}
//printf("open_private_key success to PEM_read_bio_RSAPrivateKey!\n");
key = EVP_PKEY_new();
if (NULL == key)
{
printf("open_private_key EVP_PKEY_new failed\n");
RSA_free(rsa);
return NULL;
}
EVP_PKEY_assign_RSA(key, rsa);
return key;
}
EVP_PKEY * getEvpPublicKeyByCharArray(unsigned char * publicKeyStr, int pub_key_len){
X509_PUBKEY *p = d2i_X509_PUBKEY(NULL, (const unsigned char**)&publicKeyStr, pub_key_len);
pub_key_len=p->public_key->length;
//printfOutResult((unsigned char *)p->public_key->data, pub_key_len);
RSA *rsa = d2i_RSAPublicKey(NULL, (const unsigned char**)&p->public_key->data, p->public_key->length);
if (rsa == NULL)
{
printf("open_public_key failed to d2i_RSAPublicKey!\n");
RSA_free(rsa);
return NULL;
}
//printf("open_public_key success to d2i_RSAPublicKey!\n");
EVP_PKEY* key = EVP_PKEY_new();
if (NULL == key)
{
printf("open_public_key EVP_PKEY_new failed\n");
RSA_free(rsa);
return NULL;
}
EVP_PKEY_assign_RSA(key, rsa);
return key;
}
java取得publickey与privatekey :
public static RSAPublicKey loadPublicKeyByString(String publicKeyString)
throws Exception {
try {
byte[] buffer = Base64.decode(publicKeyString);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
} catch (NullPointerException e) {
throw new Exception("公钥数据为空");
} catch (NoSuchAlgorithmException e) {
throw new Exception("无此算法");
} catch (InvalidKeySpecException e) {
throw new Exception("公钥数据为空");
}
}
public static RSAPrivateKey loadPrivateKeyByString(String privateKeyString)
throws Exception {
try {
byte[] buffer = Base64.decode(privateKeyString);
// PKCS12EncodedKeySpec keySpec=new PKCs1
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
} catch (NoSuchAlgorithmException e) {
throw new Exception("无此算法");
} catch (InvalidKeySpecException e) {
throw new Exception("私钥非法");
}
}