703
社区成员
发帖
与我相关
我的任务
分享
/*RSA公钥加密方法*/
STDMETHODIMP CsafeEdit::RsaEncrypt(BSTR strPublicKey)
{
//g_m_string保存了明文字符,这段代码可以忽略 BEGIN
int len = g_m_String.Length() + 2;
BSTR str = (BSTR)ALLOC(len * 2);
if (str == NULL)
{
return S_FALSE;
}
if (!g_m_String.B_STR(str, len * 2))
{
FREE(str);
return S_FALSE;
}
char *mingwen = _com_util::ConvertBSTRToString(str);
FREE(str);
g_m_String.Clear();
//g_m_string保存了明文字符,这段代码可以忽略 END
char *p_en; //接收加密后的密文
int flen, rsa_len;
//这段代码是将jsp页面传过来的公钥转换成OPENSSL可识别的公钥 BEGIN
_bstr_t bstr_t(strPublicKey);
string pubKey(bstr_t);
int nPublicKeyLen = pubKey.size();
for (int i = 64; i < nPublicKeyLen; i += 64)
{
if (pubKey[i] != '\n')
{
pubKey.insert(i, "\n");
}
i++;
}
pubKey.insert(0, "-----BEGIN PUBLIC KEY-----\n");
pubKey.append("\n-----END PUBLIC KEY-----\n");
//这段代码是将jsp页面传过来的公钥转换成OPENSSL可识别的公钥 END
//接下来就是OPENSSL RSA公钥加密 BEGIN
BIO *bio = NULL;
RSA *rsa = NULL;
char *chPublicKey = const_cast<char *>(pubKey.c_str());
if ((bio = BIO_new_mem_buf(chPublicKey, -1)) == NULL) //从字符串读取RSA公钥
{
cout << "BIO_new_mem_buf failed!" << endl;
}
rsa = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL); //从bio结构中得到rsa结构
if (!rsa)
{
ERR_load_crypto_strings();
char errBuf[512];
ERR_error_string_n(ERR_get_error(), errBuf, sizeof(errBuf));
cout << "load public key failed[" << errBuf << "]" << endl;
BIO_free_all(bio);
return NULL;
}
flen = strlen(mingwen); //获取明文长度,好像没用到
rsa_len = RSA_size(rsa);
//下面的一段儿代码是有疑问的地方,包括给密文分配空间p_en = (char *)malloc(rsa_len + 1); 还有
//RSA_PKCS1_PADDING方式rsa_len - 11是否正确等等
p_en = (char *)malloc(rsa_len + 1);
memset(p_en, 0, rsa_len + 1);
if (RSA_public_encrypt(rsa_len - 11, (unsigned char *)mingwen, (unsigned char*)p_en, rsa, RSA_PKCS1_PADDING)<0){
return NULL;
}
RSA_free(rsa);
//下面是将密文转为16进制字符串
BIGNUM *rs;
rs = BN_new();
BN_bin2bn((unsigned char *)p_en, strlen(p_en), rs);
char *tmpData = BN_bn2hex(rs); //将密文转为16进制字符串
int dest_len = strlen(tmpData);
for (size_t i = 0; i < dest_len; i++)
{
g_m_String.Append(tmpData[i]); //添加到返回jsp页面的字符串中
}
return S_OK;
}
/*
encryptedData:是16进制密文调用hexStringToBytes方法得到的字节数组
*/
public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey)
throws Exception {
//获取私钥
byte[] keyBytes = Base64Utils.decode(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache = null;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > 128) {
cache = cipher.doFinal(encryptedData, offSet, 128);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
}
public static byte[] hexStringToBytes(String hexString) {
if (hexString == null || hexString.equals("")) {
return null;
}
hexString = hexString.toUpperCase();
int length = hexString.length() / 2;
char[] hexChars = hexString.toCharArray();
byte[] d = new byte[length];
for (int i = 0; i < length; i++) {
int pos = i * 2;
d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
}
return d;
}
private static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}