ECC加密我查了一些资料显示在jdk中尚未实现完整加密方案,需要加入jar包,使用BC的解决方案,引用的maven仓库jar包如下:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.60</version>
</dependency>
ECCUtil加密工具类代码如下:
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import org.bouncycastle.jce.interfaces.ECPrivateKey;
import org.bouncycastle.jce.interfaces.ECPublicKey;
public class ECCUtil {
static {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
}
/**
* 生成秘钥对
*
* @return
* @throws Exception
*/
public static KeyPair getKeyPair() throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "BC");
keyPairGenerator.initialize(256, new SecureRandom());
KeyPair keyPair = keyPairGenerator.generateKeyPair();
return keyPair;
}
/**
* 取得私钥
*
* @param keyMap
* @return
* @throws Exception
*/
public static String getPrivateKey(KeyPair keyPair) throws Exception {
ECPrivateKey privateKey = (ECPrivateKey) keyPair.getPrivate();
return Base64Util.encryptBASE64(privateKey.getEncoded());
}
/**
* 取得公钥
*
* @param keyMap
* @return
* @throws Exception
*/
public static String getPublicKey(KeyPair keyPair) throws Exception {
ECPublicKey publicKey = (ECPublicKey) keyPair.getPublic();
return Base64Util.encryptBASE64(publicKey.getEncoded());
}
/**
* 将Base64编码后的公钥转换成PublicKey对象
*
* @param pubStr
* @return
* @throws Exception
*/
public static ECPublicKey string2PublicKey(String pubStr) throws Exception {
byte[] keyBytes = Base64Util.decryptBASE64(pubStr);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC");
ECPublicKey publicKey = (ECPublicKey) keyFactory.generatePublic(keySpec);
return publicKey;
}
/**
* 将Base64编码后的私钥转换成PrivateKey对象
*
* @param priStr
* @return
* @throws Exception
*/
public static ECPrivateKey string2PrivateKey(String priStr) throws Exception {
byte[] keyBytes = Base64Util.decryptBASE64(priStr);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC");
ECPrivateKey privateKey = (ECPrivateKey) keyFactory.generatePrivate(keySpec);
return privateKey;
}
/**
* 公钥加密为byte字节
*
* @param content
* @param publicKey
* @return
* @throws Exception
*/
public static byte[] publicEncrypt(byte[] content, PublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance("ECIES", "BC");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] bytes = cipher.doFinal(content);
return bytes;
}
/**
* 公钥加密转为字符串
*
* @param content
* @param publicKey
* @return
* @throws Exception
*/
public static String publicEncrypt(String content, PublicKey publicKey) throws Exception {
byte[] contentBytes = Base64Util.stringToByteArray(content);
return Base64Util.encryptBASE64(publicEncrypt(contentBytes, publicKey));
}
/**
* 私钥解密为byte字节
*/
public static byte[] privateDecrypt(byte[] content, PrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance("ECIES", "BC");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] bytes = cipher.doFinal(content);
return bytes;
}
/**
* 私钥解密为字符串
*/
public static String privateDecrypt(String content, PrivateKey privateKey) throws Exception {
byte[] contentBytes = Base64Util.decryptBASE64(content);
return new String(privateDecrypt(contentBytes, privateKey));
}
/**
* base64编码公钥加密为字符串
*/
public static String publicEncrypt(String content, String publicKeyBase64Str) throws Exception {
PublicKey publicKey = string2PublicKey(publicKeyBase64Str);
byte[] contentBytes = Base64Util.stringToByteArray(content);
return Base64Util.encryptBASE64(publicEncrypt(contentBytes, publicKey));
}
/**
* base64编码私钥解密为字符串
*/
public static String privateDecrypt(String content, String privateKeyBase64Str) throws Exception {
PrivateKey privateKey=string2PrivateKey(privateKeyBase64Str);
byte[] contentBytes = Base64Util.decryptBASE64(content);
return new String(privateDecrypt(contentBytes, privateKey));
}
}
AES加密模式可选择的模式有许多种类,我用的AES/CBC/PKCS5Padding加密模式,此模式需要加入一个向量参数,增加加密强度,也可选择其他模式,不需要向量参数的参数个数不同.
AESUtil加密工具类如下:
import java.io.UnsupportedEncodingException;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class AESUtil {
// 给定的默认密钥
private static final String ENCRYPTION_KEY = "RwcmlVpg";
// 使用AES/CBC/PKCS5Padding模式,加入的向量值
private static final String ENCRYPTION_IV = "4e5Wa71fYoT7MFEX";
// 加密模式
private static final String AESTYPE = "AES/CBC/PKCS5Padding";
/**
* 生成密钥
*
* @return
* @throws Exception
*/
public static String genKeyAES() throws Exception {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256);
SecretKey key = keyGen.generateKey();
String base64Str = Base64Util.encryptBASE64(key.getEncoded());
return base64Str;
}
/**
* 使用默认给定密钥加密
*
* @param src
* @return
*/
public static String encrypt(String src) {
try {
Cipher cipher = Cipher.getInstance(AESTYPE);
cipher.init(Cipher.ENCRYPT_MODE, makeKey(), makeIv());
return Base64Util.encryptBASE64(cipher.doFinal(src.getBytes()));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 使用默认给定密钥解密
*
* @param src
* @return
*/
public static String decrypt(String src) {
String decrypted = "";
try {
Cipher cipher = Cipher.getInstance(AESTYPE);
cipher.init(Cipher.DECRYPT_MODE, makeKey(), makeIv());
decrypted = new String(cipher.doFinal(Base64Util.decryptBASE64(src)));
} catch (Exception e) {
throw new RuntimeException(e);
}
return decrypted;
}
/**
* 使用生成的密钥加密
*
* @param src
* @param key
* @return
*/
public static String encrypt(String src, SecretKey key) {
try {
Cipher cipher = Cipher.getInstance(AESTYPE);
cipher.init(Cipher.ENCRYPT_MODE, key, makeIv());
return Base64Util.encryptBASE64(cipher.doFinal(src.getBytes()));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 使用生成的base64密钥加密
*
* @param src
* @param key
* @return
*/
public static String encrypt(String src, String keybase64Str) {
try {
SecretKey key=loadKeyAES(keybase64Str);
Cipher cipher = Cipher.getInstance(AESTYPE);
cipher.init(Cipher.ENCRYPT_MODE, key, makeIv());
return Base64Util.encryptBASE64(cipher.doFinal(src.getBytes()));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 使用生成的密钥解密
*
* @param src
* @param key
* @return
*/
public static String decrypt(String src, SecretKey key) {
String decrypted = "";
try {
Cipher cipher = Cipher.getInstance(AESTYPE);
cipher.init(Cipher.DECRYPT_MODE, key, makeIv());
decrypted = new String(cipher.doFinal(Base64Util.decryptBASE64(src)));
} catch (Exception e) {
throw new RuntimeException(e);
}
return decrypted;
}
/**
* 使用生成的base64密钥解密
*
* @param src
* @param key
* @return
*/
public static String decrypt(String src, String keybase64Str) {
String decrypted = "";
try {
SecretKey key=loadKeyAES(keybase64Str);
Cipher cipher = Cipher.getInstance(AESTYPE);
cipher.init(Cipher.DECRYPT_MODE, key, makeIv());
decrypted = new String(cipher.doFinal(Base64Util.decryptBASE64(src)));
} catch (Exception e) {
throw new RuntimeException(e);
}
return decrypted;
}
static AlgorithmParameterSpec makeIv() {
try {
return new IvParameterSpec(ENCRYPTION_IV.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
static Key makeKey() {
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] key = md.digest(ENCRYPTION_KEY.getBytes("UTF-8"));
return new SecretKeySpec(key, "AES");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
/**
* 将Base64编码后的AES秘钥转换成SecretKey对象
*
* @param base64Key
* @return
* @throws Exception
*/
public static SecretKey loadKeyAES(String base64Key) throws Exception {
byte[] bytes = Base64Util.decryptBASE64(base64Key);
SecretKeySpec key = new SecretKeySpec(bytes, "AES");
return key;
}
/**
* 使用传入的参数密码生成密钥加密
*
* @param content
* @param password
* @return
*/
public static String encryptByPassword(String content, String password) {
try {
// "AES":请求的密钥算法的标准名称
KeyGenerator kgen = KeyGenerator.getInstance("AES");
// 256:密钥生成参数;securerandom:密钥生成器的随机源
SecureRandom securerandom = SecureRandom.getInstance("SHA1PRNG");
securerandom.setSeed(tohash256Deal(password));
kgen.init(256, securerandom);
// 生成秘密(对称)密钥
SecretKey secretKey = kgen.generateKey();
// 返回基本编码格式的密钥
byte[] enCodeFormat = secretKey.getEncoded();
// 根据给定的字节数组构造一个密钥。enCodeFormat:密钥内容;"AES":与给定的密钥内容相关联的密钥算法的名称
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
// 将提供程序添加到下一个可用位置
Security.addProvider(new BouncyCastleProvider());
// 创建一个实现指定转换的 Cipher对象,该转换由指定的提供程序提供。
// "AES/ECB/PKCS7Padding":转换的名称;"BC":提供程序的名称
Cipher cipher = Cipher.getInstance(AESTYPE);
cipher.init(Cipher.ENCRYPT_MODE, key, makeIv());
return Base64Util.encryptBASE64(cipher.doFinal(content.getBytes()));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 使用传入的参数密码生成密钥解密
*
* @param content
* @param password
* @return
*/
public static String decryptByPassword(String content, String password) {
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom securerandom = SecureRandom.getInstance("SHA1PRNG");
securerandom.setSeed(tohash256Deal(password));
kgen.init(256, securerandom);
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance(AESTYPE);
cipher.init(Cipher.DECRYPT_MODE, key, makeIv());
return new String(cipher.doFinal(Base64Util.decryptBASE64(content)));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static byte[] tohash256Deal(String datastr) {
try {
MessageDigest digester = MessageDigest.getInstance("SHA-256");
digester.update(datastr.getBytes());
byte[] hex = digester.digest();
return hex;
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e.getMessage());
}
}
}
SHA256Util加密工具类如下:
import java.security.MessageDigest;
public class SHA256Util {
private static final String salt = "gfdsh@59*76%^fjkdsa24";
/**
* 不加盐加密
*
* @param origin
* @param charsetname
* @return
*/
public static String string2SHA256(String origin, String charsetname) {
String resultString = null;
try {
resultString = new String(origin);
MessageDigest md = MessageDigest.getInstance("SHA-256");
if (charsetname == null || "".equals(charsetname))
resultString = byte2Hex(md.digest(resultString.getBytes()));
else
resultString = byte2Hex(md.digest(resultString.getBytes(charsetname)));
} catch (Exception exception) {
}
return resultString;
}
/**
* 加盐加密
*
* @param origin
* @return
*/
public static String encryptSHA256(String origin) {
origin = origin + salt;
return string2SHA256(origin, "utf-8");
}
/**
* 将byte转为16进制
*
* @param bytes
* @return
*/
private static String byte2Hex(byte[] bytes) {
StringBuffer stringBuffer = new StringBuffer();
String temp = null;
for (int i = 0; i < bytes.length; i++) {
temp = Integer.toHexString(bytes[i] & 0xFF);
if (temp.length() == 1) {
// 1得到一位的进行补0操作
stringBuffer.append("0");
}
stringBuffer.append(temp);
}
return stringBuffer.toString();
}
}
上述工具类使用了base64编码,编码工具类如下:
Base64Util编码工具类:
import java.io.UnsupportedEncodingException;
import java.util.Base64;
public class Base64Util {
public static byte[] decryptBASE64(String data) {
return Base64.getDecoder().decode(data);// Base64..decodeBase64(data);
}
public static String encryptBASE64(byte[] data) {
return Base64.getEncoder().encodeToString(data);// new String(Base64.encodeBase64(data));
}
public static String byteArrayToString(byte[] byteArray) {
try {
return new String(byteArray, "UTF8");
} catch (final UnsupportedEncodingException e) {
return new String(byteArray);
}
}
public static byte[] stringToByteArray(String input) {
try {
return input.getBytes("UTF-8");
} catch (UnsupportedEncodingException fallbackToDefault) {
return input.getBytes();
}
}
}
jdk对加密强度有一定限制,如果加密工具类报错,可能与jdk加密强度有关,可以下载jdk的加密扩展包,过程如下:
去jdk官网下载加密扩展包,如果是jdk8,
下载jce_policy-8.zip扩展包
下载下来以后,需要将local_policy.jar 和 US_export_policy.jar替换掉***\Java\jdk1.8.0_91\jre\lib\security下面的相同的两个jar包。