最近一直在做与第三方的支付业务,因为数据涉及到了钱,所以交互的数据保密性非常的重要!主要应用的是RSA加密机制,整理一下共享给大家!
1、生成加密证书
1)产生证书的工具:openssl;openssl的官方推荐网站下载:http://slproweb.com/products/Win32OpenSSL.html
2)配置文件:我下载的是win-64位轻量版的:Win64OpenSSL-1_0_2f.exe,下载之后解压到C盘(我刚开始是解压到其他盘的,但是出现错误:can’t open config file: /usr/local/ssl/openssl.cnf,有人说配置环境变量:set OPENSSL_CONF=..confopenssl.cnf ;我是了不好使,大家查出来是什么问题可以告诉我一下,哈哈)在C盘根目录依次建立usr/local/ssl/openssl.cnf文件后,下载地址:http://download.csdn.net/detail/qq_32347977/9396321
3)生成采用des3算法保护的私钥:
OpenSSL> genrsa -des3 -out private-rsa.key 1024
命令执行过程中的提示信息Enter pass phrase 的含义是输入用来保护私钥文件的密码(不要超过6位),我的是123456。
4) 生成公钥证书:
OpenSSL> req -new -x509 -key private-rsa.key -days 750 -out public-rsa.cer
该过程除了最开始时需要输入私钥文件的保护密码之外,其他需要的输入均可直接回车忽略,不影响正常使用。
5)生成PKCS12 格式Keystore:
OpenSSL> pkcs12 -export -name test-alias -in public-rsa.cer -inkey private-rsa.key -out user-rsa.pfx
这样就ok了。
AES工具类:
package com.alex.util;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class AES {
public static final String CHAR_ENCODING = "UTF-8";
public static final String AES_ALGORITHM = "AES/ECB/PKCS5Padding";
/**
* 加密
*
* @param / data
* 待加密密内容
* @param /key
* 加密密钥
* @return
*/
public static byte[] encrypt(byte[] data, byte[] key) {
if(key.length!=16){
throw new RuntimeException("Invalid AES key length (must be 16 bytes)");
}
try {
SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec seckey = new SecretKeySpec(enCodeFormat,"AES");
Cipher cipher = Cipher.getInstance(AES_ALGORITHM);// 创建密码器
cipher.init(Cipher.ENCRYPT_MODE, seckey);// 初始化
byte[] result = cipher.doFinal(data);
return result; // 加密
} catch (Exception e){
throw new RuntimeException("encrypt fail!", e);
}
}
/**
* 解密
*
* @param / content
* 待解密内容
* @param /password
* 解密密钥
* @return
*/
public static byte[] decrypt(byte[] data, byte[] key) {
if(key.length!=16){
throw new RuntimeException("Invalid AES key length (must be 16 bytes)");
}
try {
SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec seckey = new SecretKeySpec(enCodeFormat, "AES");
Cipher cipher = Cipher.getInstance(AES_ALGORITHM);// 创建密码器
cipher.init(Cipher.DECRYPT_MODE, seckey);// 初始化
byte[] result = cipher.doFinal(data);
return result; // 加密
} catch (Exception e){
throw new RuntimeException("decrypt fail!", e);
}
}
public static String encryptToBase64(String data, String key){
try {
byte[] valueByte = encrypt(data.getBytes(CHAR_ENCODING), key.getBytes(CHAR_ENCODING));
return new String(Base64.encode(valueByte));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("encrypt fail!", e);
}
}
public static String decryptFromBase64(String data, String key){
try {
byte[] originalData = Base64.decode(data.getBytes());
byte[] valueByte = decrypt(originalData, key.getBytes(CHAR_ENCODING));
return new String(valueByte, CHAR_ENCODING);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("decrypt fail!", e);
}
}
public static String encryptWithKeyBase64(String data, String key){
try {
byte[] valueByte = encrypt(data.getBytes(CHAR_ENCODING), Base64.decode(key.getBytes()));
return new String(Base64.encode(valueByte));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("encrypt fail!", e);
}
}
public static String decryptWithKeyBase64(String data, String key){
try {
byte[] originalData = Base64.decode(data.getBytes());
byte[] valueByte = decrypt(originalData, Base64.decode(key.getBytes()));
return new String(valueByte, CHAR_ENCODING);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("decrypt fail!", e);
}
}
public static byte[] genarateRandomKey(){
KeyGenerator keygen = null;
try {
keygen = KeyGenerator.getInstance(AES_ALGORITHM);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(" genarateRandomKey fail!", e);
}
SecureRandom random = new SecureRandom();
keygen.init(random);
Key key = keygen.generateKey();
return key.getEncoded();
}
public static String genarateRandomKeyWithBase64(){
return new String(Base64.encode(genarateRandomKey()));
}
}
Base64工具类:
package com.alex.util;
import java.io.UnsupportedEncodingException;
public class Base64 {
/**
* Chunk size per RFC 2045 section 6.8.
*
* <p>The {@value} character limit does not count the trailing CRLF, but counts
* all other characters, including any equal signs.</p>
*
* @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 6.8</a>
*/
static final int CHUNK_SIZE = 76;
/**
* Chunk separator per RFC 2045 section 2.1.
*
* @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 2.1</a>
*/
static final byte[] CHUNK_SEPARATOR = "
".getBytes();
/**
* The base length.
*/
static final int BASELENGTH = 255;
/**
* Lookup length.
*/
static final int LOOKUPLENGTH = 64;
/**
* Used to calculate the number of bits in a byte.
*/
static final int EIGHTBIT = 8;
/**
* Used when encoding something which has fewer than 24 bits.
*/
static final int SIXTEENBIT = 16;
/**
* Used to determine how many bits data contains.
*/
static final int TWENTYFOURBITGROUP = 24;
/**
* Used to get the number of Quadruples.
*/
static final int FOURBYTE = 4;
/**
* Used to test the sign of a byte.
*/
static final int SIGN = -128;
/**
* Byte used to pad output.
*/
static final byte PAD = (byte) '=';
// Create arrays to hold the base64 characters and a
// lookup for base64 chars
private static byte[] base64Alphabet = new byte[BASELENGTH];
private static byte[] lookUpBase64Alphabet = new byte[LOOKUPLENGTH];
// Populating the lookup and character arrays
static {
for (int i = 0; i < BASELENGTH; i++) {
base64Alphabet[i] = (byte) -1;
}
for (int i = 'Z'; i >= 'A'; i--) {
base64Alphabet[i] = (byte) (i - 'A');
}
for (int i = 'z'; i >= 'a'; i--) {
base64Alphabet[i] = (byte) (i - 'a' + 26);
}
for (int i = '9'; i >= '0'; i--) {
base64Alphabet[i] = (byte) (i - '0' + 52);
}
base64Alphabet['+'] = 62;
base64Alphabet['/'] = 63;
for (int i = 0; i <= 25; i++) {
lookUpBase64Alphabet[i] = (byte) ('A' + i);
}
for (int i = 26, j = 0; i <= 51; i++, j++) {
lookUpBase64Alphabet[i] = (byte) ('a' + j);
}
for (int i = 52, j = 0; i <= 61; i++, j++) {
lookUpBase64Alphabet[i] = (byte) ('0' + j);
}
lookUpBase64Alphabet[62] = (byte) '+';
lookUpBase64Alphabet[63] = (byte) '/';
}
private static boolean isBase64(byte octect) {
if (octect == PAD) {
return true;
} else if (base64Alphabet[octect] == -1) {
return false;
} else {
return true;
}
}
/**
* Tests a given byte array to see if it contains
* only valid characters within the Base64 alphabet.
*
* @param arrayOctect byte array to test
* @return true if all bytes are valid characters in the Base64
* alphabet or if the byte array is empty; false, otherwise
*/
public static boolean isArrayByteBase64(byte[] arrayOctect) {
arrayOctect = discardWhitespace(arrayOctect);
int length = arrayOctect.length;
if (length == 0) {
// shouldn't a 0 length array be valid base64 data?
// return false;
return true;
}
for (int i = 0; i < length; i++) {
if (!isBase64(arrayOctect[i])) {
return false;
}
}
return true;
}
/**
* Encodes binary data using the base64 algorithm but
* does not chunk the output.
*
* @param binaryData binary data to encode
* @return Base64 characters
*/
public static byte[] encodeBase64(byte[] binaryData) {
return encodeBase64(binaryData, false);
}
/**
* Encodes binary data using the base64 algorithm and chunks
* the encoded output into 76 character blocks
*
* @param binaryData binary data to encode
* @return Base64 characters chunked in 76 character blocks
*/
public static byte[] encodeBase64Chunked(byte[] binaryData) {
return encodeBase64(binaryData, true);
}
/**
* Decodes a byte[] containing containing
* characters in the Base64 alphabet.
*
* @param pArray A byte array containing Base64 character data
* @return a byte array containing binary data
*/
public static byte[] decode(byte[] pArray) {
return decodeBase64(pArray);
}
/**
* Encodes binary data using the base64 algorithm, optionally
* chunking the output into 76 character blocks.
*
* @param binaryData Array containing binary data to encode.
* @param isChunked if isChunked is true this encoder will chunk
* the base64 output into 76 character blocks
* @return Base64-encoded data.
*/
public static byte[] encodeBase64(byte[] binaryData, boolean isChunked) {
int lengthDataBits = binaryData.length * EIGHTBIT;
int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
byte encodedData[] = null;
int encodedDataLength = 0;
int nbrChunks = 0;
if (fewerThan24bits != 0) {
//data not divisible by 24 bit
encodedDataLength = (numberTriplets + 1) * 4;
} else {
// 16 or 8 bit
encodedDataLength = numberTriplets * 4;
}
// If the output is to be "chunked" into 76 character sections,
// for compliance with RFC 2045 MIME, then it is important to
// allow for extra length to account for the separator(s)
if (isChunked) {
nbrChunks =
(CHUNK_SEPARATOR.length == 0 ? 0 : (int) Math.ceil((float) encodedDataLength / CHUNK_SIZE));
encodedDataLength += nbrChunks * CHUNK_SEPARATOR.length;
}
encodedData = new byte[encodedDataLength];
byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
int encodedIndex = 0;
int dataIndex = 0;
int i = 0;
int nextSeparatorIndex = CHUNK_SIZE;