簡介:
由於在工作使用中需要各種語言進行RSA加密,並在Java端進行解密,但由於RSA再進行加解密時,由於待加密字符串長度有限制,故在不考慮性能得情況下,自己封裝了一下加解密程序
java端代碼如下:
package com.example.demo;
import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Base64;
public class RSAHelperBak {
/**
*私有數據成員,主要是公鑰和私鑰
*由程序自己產生,公鑰需傳遞給通信另一方
*/
private static String publicKey;
private static String privateKey;
/**
* 產生公鑰和私鑰
*/
private static void genKeys() throws Exception{
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
//密鑰位數
keyPairGen.initialize(1024);
//密鑰對
KeyPair keyPair = keyPairGen.generateKeyPair();
// 公鑰
PublicKey pubKey = (RSAPublicKey) keyPair.getPublic();
// 私鑰
PrivateKey privKey = (RSAPrivateKey) keyPair.getPrivate();
publicKey= getKeyString(pubKey);
privateKey= getKeyString(privKey);
}
/**
*獲取程序自動生成的公鑰
* @return 返回公鑰
*/
public static String getPubKey()
{
return publicKey;
}
/**
*獲取程序自動生成的私鑰
* @return 返回私鑰
*/
public static String getPrivKey()
{
return privateKey;
}
/**
* 得到公鑰
* @param key 密鑰字符串(經過base64編碼)
* @throws Exception
*/
public static PublicKey getPublicKey(String key) throws Exception {
byte[] keyBytes;
keyBytes = Base64.getDecoder().decode(key);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}
/**
* 得到私鑰
* @param key 密鑰字符串(經過base64編碼)
* @throws Exception
*/
public static PrivateKey getPrivateKey(String key) throws Exception {
byte[] keyBytes;
keyBytes = Base64.getDecoder().decode(key);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}
/**
* 得到密鑰字符串(經過base64編碼)
* @return
*/
public static String getKeyString(Key key) throws Exception {
byte[] keyBytes = key.getEncoded();
String s = Base64.getEncoder().encodeToString(keyBytes);
return s;
}
/**
*利用Go語言產生的公鑰加密
* @param pubkey_from_go 從服務器(go語言實現)獲取的公鑰
* @param plainText 需要加密的字符串
*/
public static String encByGoPubKey(String pubkey_from_go,String plainText) throws Exception {
//加解密類
Cipher cipher = Cipher.getInstance("RSA");//Cipher.getInstance("RSA/ECB/PKCS1Padding");
byte[] plainTextBytes = plainText.getBytes();
//用Go語言產生的公鑰加密
PublicKey pubkey_go=getPublicKey(pubkey_from_go);
cipher.init(Cipher.ENCRYPT_MODE, pubkey_go);
byte[] enBytes = cipher.doFinal(plainTextBytes);
// String encryptString = (new BASE64Encoder()).encode(enBytes);
// String encryptString = Arrays.toString(Base64.encode(enBytes));
String encryptString = Base64.getEncoder().encodeToString(enBytes);
return encryptString;
}
private static final int MAX_ENCRYPT_BLOCK = 117;
/**
* 使用java公鑰進行加密
*/
public static String encrpytByJavaPublicKey(String publicKey_from_java,String plain_txt) throws Exception{
PublicKey publicKey = getPublicKey(publicKey_from_java);
Cipher cipher = Cipher.getInstance("RSA");//Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] data = plain_txt.getBytes();
int inputLen = plain_txt.length();
int offSet = 0;
String result = "";
int i = 0;
// 對數據分段加密
while (inputLen - offSet > 0)
{
if ( inputLen - offSet > MAX_ENCRYPT_BLOCK)
{
byte[] cache = cipher.doFinal( data, offSet, MAX_ENCRYPT_BLOCK);
if(i == 0) {
result += Base64.getEncoder().encodeToString(cache);
}else
{
result += " " + Base64.getEncoder().encodeToString(cache);
}
}
else
{
byte[] cache = cipher.doFinal( data, offSet, inputLen - offSet);
if(i == 0) {
result = Base64.getEncoder().encodeToString(cache);
}else
{
result += " " + Base64.getEncoder().encodeToString(cache);
}
}
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
return result;
}
/**
*用私鑰解密密文(其他語言用java公鑰產生的)
*
*/
public static String decryptByJavaPrivKey(String privkey_from_java,String encryptedString) throws Exception{
//加解密類
Cipher cipher = Cipher.getInstance("RSA");//Cipher.getInstance("RSA/ECB/PKCS1Padding");
PrivateKey privateKey = getPrivateKey(privkey_from_java);
String resultSplit[] = encryptedString.split(" ");
ArrayList<byte[]> result = new ArrayList<byte[]>();
int length_byte = 0;
for (String x : resultSplit){
byte[] enBytes= Base64.getDecoder().decode(x);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[]deBytes = cipher.doFinal(enBytes);
result.add(deBytes);
}
for (byte[] x: result) {
length_byte += x.length;
}
byte[] all_byte = new byte[length_byte];
int countLength = 0;
for (byte[] x: result){
System.arraycopy(x,0,all_byte,countLength,x.length);
countLength += x.length;
}
String decryptString=new String(all_byte);
return decryptString;
}
public static void main(String[] args) throws Exception {
genKeys();
String publicKeyString =getPubKey();
System.out.println("public key:\n" + publicKeyString);
String privateKeyString = getPrivKey();
System.out.println("private key:\n" + privateKeyString);
String pubKey_from_java = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDGIAJm8RuOcx6he1ZlSUBH2bg2ZQadi/wsnv36a7PwZds33ZSmzqLdLTUj9tHUqPKtUuKsYBvsYDy307aSLndYmBhaTYlG9K9gF07CPAK46jThkvebDCEYoWjhfRFKiIgbrBWkZLAWUvJ80awFWcmkY29Y6T3+a2L1iZ10WY2umwIDAQAB";
String privKey_from_java = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMYgAmbxG45zHqF7VmVJQEfZuDZlBp2L/Cye/fprs/Bl2zfdlKbOot0tNSP20dSo8q1S4qxgG+xgPLfTtpIud1iYGFpNiUb0r2AXTsI8ArjqNOGS95sMIRihaOF9EUqIiBusFaRksBZS8nzRrAVZyaRjb1jpPf5rYvWJnXRZja6bAgMBAAECgYBdKCnY+19ooGpzpUmfQE0QO6fpM6FjrLF6zZtABypJS6tC3lYKBLkBZENLUL+izXml04YvZNVcVHfYO5zpqR2F38z7mCfo4nRVGZS0H92+lKjbS9cZpXcaMrb8+/6+ljQC5fIZK/eoiVls0oAVPb5nZ69F5lL5TRiby3g1P3WpgQJBAOaboEg/BrwXcPTH2EVstUnggjUSGzfArskEkEtfQ0n63EUz+GmyHxNINViD0HNk9A6I3WpuFI8iZbPLl2hWiEECQQDb8MGWeF/jA8Egu/PNlJ+B7aP9jKljVixFQxBtiaG3kpBPdDnXWGpNGVN2OanD2ENzcR+w4iTCzn+zfhl1N1/bAkEArE1lcfWdi5YcMNjM7/psbfmQcCTKL1sJfWqqgZZ5CWKliBNvrVGIRHj0WuGKM14fuGhsv2Pmepfh03fv9eaJwQJAfcWWnpplkuchuLtidwxnjqA7qBGZB+JOXKk2Kr2KyfQ5LAZ10SyRVVeHP9NHvmPcZpapHbikdvYpVpZkroAlAwJAWCeoaZMTCMVkT3Su/qNpgcZz4IL0HPqQdwAh8rlBHiJxdlLxv6vk5lgHTRTjZz475+5ch6tKEa82nv62DfwveA==";
String test1 = "{ \"name\": \"漏洞掃描\", \"leveIno\": 1, \"filename\": \"logTool_c.c\", \"funcName\": \"uploadToolsInfo\", \"lineno\": 199, \"createTime\": 1576639355, \"processId\": 9361, \"version\": \"1.2.0\", \"message\": { \"exetime\": 100, \"client\": \"北京市檢察院\", \"result\": \"掃描結果\", \"userInfo\": \"研發組\", \"request\": \"漏洞掃描,解決問題描述\", \"ext\": \"擴展信息\" } }";
String enString = encrpytByJavaPublicKey(pubKey_from_java,test1);
System.out.println("加密後的字符串:\n" + enString);
//解密java客戶端產生的字符串
System.out.println("解密java客戶端產生的字符串");
System.out.println(decryptByJavaPrivKey(privKey_from_java,enString));
//其他語言產生的加密字符串
String enString_from_go="q8qiWiFZoSTsfpYHjbI1CpOMvvnBm5IueZcHyBboAzEYSidh8wj//gYlw6GcXIMprkfKpAClSlZ5xVtulzuzwogPG4NyXDMs1dFvSEXKGShxV8XbYBJwmrPNCpdpm/HtCgRwtGXG6DMn9r8b4IAi+09uYxhRY3Y+FADYHlgjwmE=";
String decryptString=decryptByJavaPrivKey(privKey_from_java,enString_from_go);
System.out.println("解密其他語言產生的字符串:\n"+decryptString);
}
}
C語言客戶端產生加密得代碼,文件名爲bak.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/sha.h>
#include <openssl/hmac.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
const char *RSA_SK = "key.key";
const char *RSA_PK = "publicKey.key";
#define MAX_ENCRYPT_BLOCK 116
#define MAX_ENCRYPT_COUNT 8
#define MAX_ENCRYPT_LONG 172
char *base64(const char *input, size_t length, char *result, size_t size)
{
BIO * bmem = NULL;
BIO * b64 = NULL;
BUF_MEM * bptr = NULL;
b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
bmem = BIO_new(BIO_s_mem());
b64 = BIO_push(b64, bmem);
BIO_write(b64, input, length);
BIO_flush(b64);
BIO_get_mem_ptr(b64, &bptr);
if(bptr->length + 1 > size)
{
BIO_free_all(b64);
return NULL;
}
memcpy(result, bptr->data, bptr->length);
result[bptr->length] = 0;
BIO_free_all(b64);
return result;
}
int rsa_encrypt_block(size_t size,unsigned char *plain_text_block,char *result,RSA *rsa,unsigned char * cipher)
{
if (0 > RSA_public_encrypt(size, plain_text_block, cipher, rsa, RSA_PKCS1_PADDING))
{
return 1;
}
base64((char *) cipher, strlen((char *) cipher), result, 1024);
return 0;
}
//0 代表成功, 1代表失敗
int rsa_encrypt(const char *plain_text, char **result, const char *pk_filename)
{
unsigned char *cipher;
int len,i = 0;
RSA *rsa;
FILE *file;
char result_tmp[1024] = {0};
if (NULL == (file = fopen(pk_filename, "rb")))
{
fprintf(stderr, "%s public key file not exist!\n", pk_filename);
return 1;
}
if (NULL == (rsa = PEM_read_RSA_PUBKEY(file, NULL, NULL, NULL )))
{
ERR_print_errors_fp(stdout);
return 1;
}
fclose(file);
len = RSA_size(rsa);
if (NULL == (cipher = (unsigned char *) malloc(len + 1)))
{
RSA_free(rsa);
return 1;
}
int inputLen = strlen((unsigned char*)plain_text);
int offset = 0;
while(inputLen - offset > 0){
int j = 0;
if(inputLen - offset > MAX_ENCRYPT_BLOCK){
while(j < MAX_ENCRYPT_COUNT){
memset(cipher, 0, len + 1);
memset(result_tmp, 0, 1024);
memcpy(result_tmp,plain_text+offset,MAX_ENCRYPT_BLOCK);
memset(result_tmp, 0, 1024);
if(1 == rsa_encrypt_block(MAX_ENCRYPT_BLOCK,(unsigned char *)plain_text+offset,result_tmp,rsa,cipher))
{
if(*result) free(*result);
RSA_free(rsa);
free(cipher);
return 1;
}
if(strlen(result_tmp) >= MAX_ENCRYPT_LONG) break;
j++;
}
if(i == 0){
*result = (char *)calloc(strlen(result_tmp),sizeof(char));
memcpy(*result,result_tmp,strlen(result_tmp));
}else{
*result = (char *)realloc(*result,strlen(*result)+strlen(result_tmp)+1);
*(*result+strlen(*result)) = ' ';
memcpy(*result+strlen(*result),result_tmp,strlen(result_tmp));
}
}else{
while(j < MAX_ENCRYPT_COUNT){
memset(cipher, 0, len + 1);
memset(result_tmp, 0, 1024);
if(1 == rsa_encrypt_block((inputLen-offset),(unsigned char *)plain_text+offset,result_tmp,rsa,cipher))
{
if(*result) free(*result);
RSA_free(rsa);
free(cipher);
return 1;
}
if(strlen(result_tmp) >= MAX_ENCRYPT_LONG) break;
j++;
}
if(i == 0){
*result = (char *)calloc(strlen(result_tmp),sizeof(char));
memcpy(*result,result_tmp,strlen(result_tmp));
}else{
*result = (char *)realloc(*result,strlen(*result)+strlen(result_tmp)+1);
*(*result+strlen(*result)) = ' ';
memcpy(*result+strlen(*result),result_tmp,strlen(result_tmp));
}
}
i++;
offset = i*MAX_ENCRYPT_BLOCK;
}
RSA_free(rsa);
free(cipher);
return 0;
}
char *debase64(char *input, size_t length, char *result, size_t size)
{
BIO * b64 = NULL;
BIO * bmem = NULL;
if(length > size)
return NULL;
memset(result, 0, size);
b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
bmem = BIO_new_mem_buf(input, length);
bmem = BIO_push(b64, bmem);
BIO_read(bmem, result, length);
BIO_free_all(bmem);
return result;
}
char *rsa_decrypt(char *cipher, char *plain_text, size_t size, const char *sk_filename)
{
FILE *file = NULL;
RSA *rsa;
int len;
if (NULL == (file = fopen(sk_filename, "rb")))
{
fprintf(stderr, "%s private key file not exist!\n", sk_filename);
return NULL ;
}
if ((rsa = PEM_read_RSAPrivateKey(file, NULL, NULL, NULL )) == NULL )
{
ERR_print_errors_fp(stdout);
return NULL ;
}
fclose(file);
len = RSA_size(rsa);
memset(plain_text, 0, size);
char temp[250];
if(NULL == debase64(cipher, strlen(cipher), temp, 250))
{
RSA_free(rsa);
fprintf(stderr, "decrypt error\n");
return NULL;
}
if (0
> RSA_private_decrypt(len, (unsigned char *) temp,
(unsigned char*) plain_text, rsa, RSA_PKCS1_PADDING))
{
RSA_free(rsa);
return NULL ;
}
RSA_free(rsa);
return plain_text;
}
int main()
{
char *source = "ssssssss將飛機飛機飛機覅姐夫姐夫姐姐飛機風機房將飛機飛機覅解放街減肥減肥減肥減肥積分jifjiefjiefie發Joe金佛i額ssssssss將飛機飛機飛機覅姐夫姐夫姐姐飛風機房將飛機飛機覅解放街減肥減肥減肥減肥積分jifjiefjiefie發Joe金佛issssssss將飛機飛機飛機覅姐夫姐夫姐姐飛機風機房將飛機飛機覅解放街減肥減肥減肥減肥積分jifjiefjiefie發Joe金i額額";
printf("%s\n",source);
char buf[8192] = {0};
char *result = NULL;
rsa_encrypt(source,&result,"./test_pub.key");
printf("%s\n",result);
return 0;
}
c客戶端得編譯方法爲:
gcc bak.c -lssl -lcrypto -g -O0