和前端进行数据交互时或者和第三方商家对接时,需要对隐私数据进行加密。单向加密,对称加密,非对称加密,其对应的算法也各式各样。java提供了统一的框架来规范(java.security)安全加密这类API。下面将一一介绍
常用的加密算法类型有三种,如下:
public static final KeyGenerator getInstance(String algorithm, String provider)
public static final KeyGenerator getInstance(String algorithm)
public final void init(int keysize)
public final void init(int keysize, SecureRandom random)
public final void init(SecureRandom random)
public final void init(AlgorithmParameterSpec params, SecureRandom random)
public final SecretKey generateKey()
public static void main(String[] args) throws Exception {
SecretKey secretKey = generatorDesKey();
System.out.println(secretKey);
}
public static SecretKey generatorDesKey() throws NoSuchAlgorithmException {
KeyGenerator keyGen = KeyGenerator.getInstance("DES");
SecureRandom random = new SecureRandom();
random.nextBytes(new byte[128]);
keyGen.init(56,random);
SecretKey key = keyGen.generateKey();
return key;
}
------------输出结果------------------
com.sun.crypto.provider.DESKey@185c3
//KeyPairGenerator.java
public static KeyPairGenerator getInstance(String algorithm)
public static KeyPairGenerator getInstance(String algorithm, String provider)
public void initialize(int keysize, SecureRandom random)
public void initialize(AlgorithmParameterSpec params, SecureRandom random)
public final KeyPair genKeyPair()
//KeyPair.java
public PublicKey getPublic()
public PrivateKey getPrivate()
public static void main(String[] args) throws Exception {
KeyPair keyPair = generatorRsaKey();
System.out.println(keyPair);
}
public static KeyPair generatorRsaKey() throws Exception {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
SecureRandom random = new SecureRandom();
random.nextBytes(new byte[516]);
keyGen.initialize(516,random);
KeyPair keyPair = keyGen.genKeyPair();
System.out.println(keyPair.getPrivate());
System.out.println(keyPair.getPublic());
return keyPair;
}
SunRsaSign RSA private CRT key, 516 bits
params: null
modulus: 126519853979546358862851378153247782379894323767375778571361894186790679401365500006956495592162216057219204240578435837612184688685910973224797092901015673
private exponent: 84346569319697572575234252102165188253262882511583852380907929457860452934243188047935652497010382336410866699832067872276413297543254894848799721123249067
Sun RSA public key, 516 bits
params: null
modulus: 126519853979546358862851378153247782379894323767375778571361894186790679401365500006956495592162216057219204240578435837612184688685910973224797092901015673
public exponent: 3
java.security.KeyPair@5010be6
❝If the key is stored on a hardware device, its specification may contain information that helps identify the key on the device ❞
❝KeySpec是一个接口,用来组成加密密钥的密钥内容的(透明)规范。如果密钥存储在硬件设备上,则其规范可以包含有助于标识该设备上的密钥的信息 ❞
public static final SecretKeyFactory getInstance(String algorithm)
public static final SecretKeyFactory getInstance(String algorithm, String provider)
public final SecretKey translateKey(SecretKey key)
public final SecretKey generateSecret(KeySpec keySpec)
public final KeySpec getKeySpec(SecretKey key, Class<?> keySpec)
public static void main(String[] args) throws Exception {
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
byte[] DESKey = "helloWWW".getBytes(StandardCharsets.UTF_8);// 设置密钥
DESKeySpec keySpec = new DESKeySpec(DESKey);// 设置密钥参数
SecretKey key = keyFactory.generateSecret(keySpec);// 得到密钥对象
System.out.println(key);
}
------------输出结果------------------
com.sun.crypto.provider.DESKey@18e49
//KeyFactory.java
public static KeyFactory getInstance(String algorithm)
public static KeyFactory getInstance(String algorithm, String provider)
public final PublicKey generatePublic(KeySpec keySpec)
public final PrivateKey generatePrivate(KeySpec keySpec)
public final <T extends KeySpec> T getKeySpec(Key key, Class<T> keySpec)
public static void main(String[] args) throws Exception {
//生成RSA秘钥对;generatorRsaKey是上面示例提供的函数
KeyPair keyPair = generatorRsaKey();
System.out.println(keyPair);
//PublicKey转KeySpec;KeySpec再转PublicKey
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(keyPair.getPublic().getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);
System.out.println(pubKey);
//PrivateKey转KeySpec;KeySpec再转PrivateKey
PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(keyPair.getPrivate().getEncoded());
PrivateKey priKey = keyFactory.generatePrivate(priKeySpec);
System.out.println(priKey);
}
java.security.KeyPair@78e03bb5
Sun RSA public key, 1024 bits
params: null
modulus: 94134923375030889337699664145116176095803777687781162111756914700229869014912695784710407302811615186395818803402552376808400599961548587586207216709744471870318354813036696801675648731428269930963470277811176883827680414539855481218813862408748594430021606927061565116386180650249935749556615770533203721821
public exponent: 65537
SunRsaSign RSA private CRT key, 1024 bits
params: null
modulus: 94134923375030889337699664145116176095803777687781162111756914700229869014912695784710407302811615186395818803402552376808400599961548587586207216709744471870318354813036696801675648731428269930963470277811176883827680414539855481218813862408748594430021606927061565116386180650249935749556615770533203721821
private exponent: 67868152791098303572124282937222322055125020915630253288684471666171190487123683962152169691286583419399765605089805755591451063493647416931630849589322449230367252892862038338916192807582203337302166911147185956153147905653905702289234855039234840869874793012808454810161546053566242403672442319692325665473
MessageDigest digest = MessageDigest.getInstance("MD5");
System.out.println(new String(digest.digest("hello world!".getBytes())));
System.out.println(new String(digest.digest("hello world!".getBytes())));
------------输出结果------------------
0���G?�w
0���G?�w
public static void main(String[] args) throws Exception {
// 初始化HmacMD5摘要算法的密钥产生器
KeyGenerator generator = KeyGenerator.getInstance("HmacMD5");
// 产生密钥
SecretKey secretKey = generator.generateKey();
//SecretKeySpec继承于SecretKey和KeySpec,因此可直接用SecretKeySpec初始化Mac
//SecretKey secretKey = new SecretKeySpec("password".getBytes(), "HmacMD5");
Mac mac = Mac.getInstance("HmacMD5");
mac.init(secretKey);
//计算摘要
String data = "hello world";
byte[] result1 = mac.doFinal(data.getBytes());
byte[] result2 = mac.doFinal(data.getBytes());
System.out.println(new String(result1).equals(new String(result2)));
}
------------输出结果------------------
true
public static void main(String[] args) throws Exception {
KeyPair keyPair = generatorRsaKey();
Signature signature = Signature.getInstance("MD5withRSA");
signature.initSign(keyPair.getPrivate());
//加解密数据
byte[] data = "hello world".getBytes();
//数据签名
signature.update(data);
byte[] digest = signature.sign();
//数据解密加验证
signature.initVerify(keyPair.getPublic());
signature.update(data);
System.out.println("验证结果:"+signature.verify(digest));
}
------------输出结果------------------
验证结果:true
public static void main(String[] args) throws Exception {
KeyPair keyPair = generatorRsaKey();
Cipher cipher = Cipher.getInstance("RSA");
// 编码前设定编码方式及密钥
cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate());
//加解密数据
byte[] data = "hello world".getBytes();
//数据签名
byte[] enData = cipher.doFinal(data);
//数据解密
cipher.init(Cipher.DECRYPT_MODE, keyPair.getPublic());
byte[] newData = cipher.doFinal(enData);
System.out.println("验证结果:"+new String(newData));
}
------------输出结果------------------
验证结果:hello world
//certificateStream是证书的输入流
public static PublicKey getPublicKeyByCer(InputStream certificateStream) throws Exception{
CertificateFactory certificateFactory = CertificateFactory.getInstance("X509");
Certificate certificate = certificateFactory.generateCertificate(certificateStream);
return certificate.getPublicKey();
}
public static void main(String[] args) throws Exception {
InputStream certificateStream = null;
//根据Certificate生成KeyStore
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(null);
keyStore.setCertificateEntry("certificate", certificateFactory.generateCertificate(certificateStream));
//加载jks文件,并生成KeyStore
KeyStore trustKeyStore = KeyStore.getInstance("jks");
FileInputStream trustKeyStoreFile = new FileInputStream("/root/trustKeyStore.jks");
trustKeyStore.load(trustKeyStoreFile, "password".toCharArray());
}
public static String postWithSSL(String url, String jsonBody) throws Exception {
SSLContext sslContext = getSslContext();
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
sslContext, new String[]{"TLSv1.2", "TLSv1.1", "TLSv1"}, null,
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(3000)
.setSocketTimeout(3000)
.build();
CloseableHttpClient client = HttpClients.custom()
.setSSLSocketFactory(sslConnectionSocketFactory)
.setDefaultRequestConfig(config).build();
HttpPost httpPost = new HttpPost(url);
//httpPost.setHeaders(headers);
httpPost.setHeader("Content-Type", "application/json; charset=utf-8");
httpPost.setHeader("Accept", "application/json");
httpPost.setEntity(new StringEntity(jsonBody, StandardCharsets.UTF_8));
HttpResponse response = client.execute(httpPost);
HttpEntity responseEntity = response.getEntity();
String result = EntityUtils.toString(responseEntity, "UTF-8");
return result;
}
//双向加密 SSLContext
private static SSLContext getSslContext() throws Exception {
//自身私钥
KeyStore identityKeyStore = KeyStore.getInstance("jks");
FileInputStream identityKeyStoreFile = new FileInputStream("/root/myServer.jks");
identityKeyStore.load(identityKeyStoreFile, "password1".toCharArray());
//服务端信任证书
KeyStore trustKeyStore = KeyStore.getInstance("jks");
FileInputStream trustKeyStoreFile = new FileInputStream("/root/trustKeyStore.jks");
trustKeyStore.load(trustKeyStoreFile, "password".toCharArray());
//构建SSLContexts
return SSLContexts.custom()
.loadKeyMaterial(identityKeyStore, "password1".toCharArray()) // load identity keystore
.loadTrustMaterial(trustKeyStore, null) // load trust keystore
.build();
}
//双向加密 SSLContext 方式二
private static SSLContext getSslContext2() throws Exception{
//自身私钥
KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
KeyStore keystore = KeyStore.getInstance("jks");
keystore.load(new FileInputStream(new File("/root/myServer.jks")), "password".toCharArray());
keyFactory.init(keystore, "password".toCharArray());
KeyManager[] keyManagers = keyFactory.getKeyManagers();
//服务端信任证书
TrustManagerFactory trustFactory = TrustManagerFactory.getInstance("SunX509");
KeyStore tsStore = KeyStore.getInstance("jks");
tsStore.load(new FileInputStream(new File("/root/trustKeyStore.jks")), "password".toCharArray());
trustFactory.init(tsStore);
TrustManager[] trustManagers = trustFactory.getTrustManagers();
//初始化SSLContext
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagers, trustManagers, null);
return sslContext;
}
[1]
网络篇:朋友面试之https认证加密过程: https://juejin.cn/post/6918203360315179022
[2]
JCA-Java加密框架: https://www.jianshu.com/p/a8194c237363
[3]
Java加密框架(JCA)简要说明: https://www.cnblogs.com/libin6505/p/10442194.html
[4]
Java加密解密之MAC: https://blog.csdn.net/x_san3/article/details/80613605
[5]
关于keyGenerator,KeyPairGenerator,SecretKeyFactory的解析: https://www.cnblogs.com/jeremy-blog/p/5289731.html
[6]
JCA 实践记录——SecretKeyFactory: https://www.jianshu.com/p/f66a0b93b919
[7]
HttpClient 双向认证: https://blog.csdn.net/xintonghanchuang/article/details/103298943
[8]
java内置可用加密算法文档: https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyGenerator
[9]
key解析: https://www.cnblogs.com/littlefishxu/p/3969180.html