基于JKS的RSA非对称加密

基于JKS的RSA非对称加密

client端程序需要调用server端的接口,通过httpClient的post的方式将参数传递过去
其中有个重要参数。

想借用xfire的加密的方式将数据传递过去,自己写个简单的Util来处理

采用的方式是
client端
data ---》 public.jks进行加密 ---》base64进行加密 ----》密文

server端
密文 ---》 base64进行解密 ---》private.jks进行解密 ----》data

在整个过程中,两方都需要有jks密钥才能成功获得数据。

测试的例子用到了如下文件
server_public.jks SERVER端的公钥
server_private.jks SERVER端的私钥
以上两个文件的保存打开密码都用的是默认的测试密码 kaishi

另外在server_private.jks中的证书别名也是测试的 server,对应密码也是测试的 server

另外jks文件可以在eclipse上安装一个插件就可以编辑和查看了,这样写程序的时候方便一些。这个
插件的ECLIPSE在线更新地址如下:
SecureX
UpdateSite: http://securex.sourceforge.net/updatesite

测试的类JKSUtil.java如下:


package com.megaeyes.ipcamera.service.webservice.tools;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;

import javax.crypto.Cipher;

import org.apache.commons.codec.binary.Base64;

import com.megaeyes.web.util.EncodeUtil;

public class JKSUtil {

public static final String PUBLIC_KEY_STORE_FILE = "E:/project/ipcamera/src/server_public.jks";

public static final String PRIVATE_KEY_STORE_FILE = "E:/project/ipcamera/src/server_private.jks";;

public static final String PUBLIC_KEY_STORE_PASS = "kaishi";

public static final String PUBLIC_KEY_STORE_ALIAS = "server";

public static final String PUBLIC_KEY_ALIAS_PASS = "server";

/**
* 得到公钥
*
* @param keyStoreFile 公钥文件名
* @param storeFilePass 公钥文件的PASS
* @param keyAlias 公钥别名
* @return 公钥
*/
public static PublicKey getPublicKey(String keyStoreFile,
String storeFilePass, String keyAlias) {
KeyStore ks;
PublicKey pubkey = null;
try {
ks = KeyStore.getInstance("JKS");
FileInputStream fin;
try {
fin = new FileInputStream(keyStoreFile);
try {
ks.load(fin, storeFilePass.toCharArray());
Certificate cert = ks.getCertificate(keyAlias);
pubkey = cert.getPublicKey();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
} catch (KeyStoreException e) {
e.printStackTrace();
}
return pubkey;
}

/**
* 得到私钥
* @param keyStoreFile 私钥文件
* @param storeFilePass 私钥文件的密码
* @param keyAlias 别名
* @param keyAliasPass 密码
* @return
*/
public static PrivateKey getPrivateKey(String keyStoreFile,
String storeFilePass, String keyAlias, String keyAliasPass) {
KeyStore ks;
PrivateKey prikey = null;
try {
ks = KeyStore.getInstance("JKS");
FileInputStream fin;
try {
fin = new FileInputStream(keyStoreFile);
try {
try {
ks.load(fin, storeFilePass.toCharArray());
//先打开文件
prikey = (PrivateKey) ks.getKey(keyAlias, keyAliasPass
.toCharArray());
//通过别名和密码得到私钥
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
} catch (KeyStoreException e) {
e.printStackTrace();
}
return prikey;
}

/**
* 加密
*
* @param key
* @param code
* @return
* @throws EncryptException
*/
public static String encrypt(Key key, String src) throws EncryptException {
byte[] data = JKSUtil.string2Bytes(src);
try {
Cipher cipher = Cipher.getInstance("RSA",
new org.bouncycastle.jce.provider.BouncyCastleProvider());
cipher.init(Cipher.ENCRYPT_MODE, key);
int blockSize = cipher.getBlockSize();// 获得加密块大小,如:加密前数据为128个
// byte,而key_size=1024
// 加密块大小为127
// byte,加密后为128个byte;因此共有2个加密块,第一个127
// byte第二个 为1个byte
int outputSize = cipher.getOutputSize(data.length);// 获得加密块加密后块大小
int leavedSize = data.length % blockSize;
int blocksSize = leavedSize != 0 ? data.length / blockSize + 1
: data.length / blockSize;
byte[] raw = new byte[outputSize * blocksSize];
int i = 0;
while (data.length - i * blockSize > 0) {
if (data.length - i * blockSize > blockSize)
cipher.doFinal(data, i * blockSize, blockSize, raw, i
* outputSize);
else
cipher.doFinal(data, i * blockSize, data.length - i
* blockSize, raw, i * outputSize);
// 这里面doUpdate方法不可用,查看源代码后发现每次doUpdate后并没有什么实际动作除了把byte[]放到
// ByteArrayOutputStream中,而最后doFinal的时候才将所有的byte[]进行加密,可是到了此时加密块大小很可能已经超出了
// OutputSize所以只好用dofinal方法。
i++;
}
return JKSUtil.bytes2StringBase64Encode(raw);
//由于输出的东东要经过URL等传送,所以用base64加密后传送
} catch (Exception e) {
throw new EncryptException(e);
}
}

/**
* 解密
*
* @param key
* @param input
* @return
* @throws EncryptException
*/
public static String decrypt(Key key, String src) throws EncryptException {
byte[] raw = JKSUtil.string2BytesBase64Decode(src);
//由于传送前进行了base64加密,所以在解码前先BASE64解密
try {
Cipher cipher = Cipher.getInstance("RSA",
new org.bouncycastle.jce.provider.BouncyCastleProvider());
cipher.init(cipher.DECRYPT_MODE, key);
int blockSize = cipher.getBlockSize();
ByteArrayOutputStream bout = new ByteArrayOutputStream(64);
int j = 0;

while (raw.length - j * blockSize > 0) {
bout.write(cipher.doFinal(raw, j * blockSize, blockSize));
j++;
}
return JKSUtil.bytes2String(bout.toByteArray());
} catch (Exception e) {
throw new EncryptException(e.getMessage());
}
}

private static String bytes2String(byte[] bts) {
String str = "";
try {
str = new String(bts, "ISO-8859-1");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return str;
}

private static String bytes2StringBase64Encode(byte[] bts) {
Base64 base64 = new Base64();
byte[] enbytes;
String str = "";
try {
enbytes = base64.encode(bts);
str = new String(enbytes, "ISO-8859-1");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return str;
}

private static byte[] string2Bytes(String str) {
byte[] debytes = null;
try {
debytes = str.getBytes("ISO-8859-1");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return debytes;
}

private static byte[] string2BytesBase64Decode(String s) {
Base64 base64 = new Base64();
byte[] debytes = null;
try {
debytes = base64.decode(s.getBytes("ISO-8859-1"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return debytes;
}

public static void main(String[] args) throws UnsupportedEncodingException {
PublicKey publicKey = JKSUtil.getPublicKey(PUBLIC_KEY_STORE_FILE,
PUBLIC_KEY_STORE_PASS, PUBLIC_KEY_STORE_ALIAS);
PrivateKey privateKey = JKSUtil.getPrivateKey(PRIVATE_KEY_STORE_FILE,
PUBLIC_KEY_STORE_PASS, PUBLIC_KEY_STORE_ALIAS,
PUBLIC_KEY_ALIAS_PASS);

String source = "0000000000000000000000000000081";
System.out.println(" source string: " + source);
String output = "";
String input = "";
try {
output = JKSUtil.encrypt(publicKey, source);
System.out.println(" encode string: " + output);
input = JKSUtil.decrypt(privateKey, output);
System.out.println(" uncode string: " + input);
} catch (EncryptException e) {
e.printStackTrace();
}
}
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值