Java 实现加密与减密只要使用在网络传输,支付等相关领域,下面分别从以下几个方面进行讲解:
1.Java实现Base64加密;
2.Java实现 消息摘要算法加密;
3.Java实现对称加密;
4.Java实现非对称加密;
5.Java实现数字签名。
1.Java实现Base64加密:
(1) 概述
按照RFC2045的定义,Base64被定义为:Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式。
(2) 常用术语
明文:待加密信息。
密文:经过加密后的明文。
加密:明文转为密文的过程。
加密算法:明文转为秘文的转换算法。
加密密钥:通过加密算法进行加密操作用的密钥。
解密:将密文转为明文的过程。
解密算法:密文转为明文的算法。
解密密钥:通过解密算法进行解密操作用的密钥。
密码分析:截获密文者试图通过分析截获的密文从而推断出来的明文或密钥的过程。
主动攻击:攻击者非法入侵密码系统,采用伪造、修改、删除等手段向系统注入假消息进行欺骗。(对密文具有破坏作用)
被动攻击:对一个保密系统采取截获密文并对其进行分析和攻击。(对密文没有破坏作用)
密码体制:由明文空间、密文空间、密钥空间、加密算法和解密算法五部分构成。
密码协议:也称安全协议,指以密码学为基础的消息交通的通信协议,目的是在网络环境中提供安全的服务。
密码系统:指用于加密、解密的系统。
柯克霍夫原则:数据的安全基于密钥而不是算法的保密。即系统的安全取决于密钥,对密钥保密,对算法公开。——现代密码设计的基本原则。
(3) 加减密基础
① 密码的分类:
a.时间
古典密码:以字符为基本加密单元。
现代密码:以信息块为基本加密单元。
b.保密内容算法
c.密码体制:
d.明文处理方法:
分组加密:指加密时将名为分成固定长度的组,用同一密钥和算法对每一块加密,输出也是固定长度的密文。多用于网络加密。
流密码:也称序列密码。指加密时每次加密一位或者一个字节明文。
e.散列函数:用来验证数据的完整性
f.数字签名:主要是针对以数字的形式存储的消息进行的处理。
(4) OSI (Open System Interconnection)安全体系:
① OSI(Open System Interconnection)安全体系
② TCP/IP安全体系:
③
TCP/IP安全体系安全服务和安全机制
(5) Java安全组成
JAC(Java Cryptography Architecture)
JCE(Java Cryptography Extension)
JSSE(Java Secure Socket Extension)
JAAS(Java Authentication and Authentication Service)
(6) BASE64算法实现
-
package com.timliu.security.base64;
-
import org.apache.commons.codec.binary.Base64;
-
import sun.misc.BASE64Decoder;
-
import sun.misc.BASE64Encoder;
-
-
public
class Base64Test{
-
public
static
final String src =
"base64 test";
-
public static void main(String[] args){
-
jdkBase64();
-
commonsCodesBase64();
-
bouncyCastleBase64();
-
}
-
-
// 用jdk实现
-
public static void jdkBase64(){
-
try
-
{
-
BASE64Encoder encoder =
new BASE64Encoder();
-
String encode = encoder.encode(src.getBytes());
-
System.out.println(
"encode:" + encode);
-
-
BASE64Decoder decoder =
new BASE64Decoder();
-
System.out.println(
"decode:" +
new String(decoder.decodeBuffer(encode)));
-
}
catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
-
-
// 用Apache的common codes实现
-
public static void commonsCodesBase64()
-
{
-
byte[] encodeBytes = Base64.encodeBase64(src.getBytes());
-
System.out.println(
"common codes encode:" +
new String(encodeBytes));
-
-
byte[] dencodeBytes = Base64.decodeBase64(encodeBytes);
-
System.out.println(
"common codes decode:" +
new String(dencodeBytes));
-
}
-
-
// 用bouncy castle实现
-
public static void bouncyCastleBase64()
-
{
-
byte[] encodeBytes = org.bouncycastle.util.encoders.Base64.encode(src.getBytes());
-
System.out.println(
"bouncy castle encode:" +
new String(encodeBytes));
-
-
byte[] dencodeBytes = org.bouncycastle.util.encoders.Base64.decode(encodeBytes);
-
System.out.println(
"bouncy castle decode:" +
new String(dencodeBytes));
-
}
-
}
2.消息摘要算法:
MD,SHA,MAC,主要用于验证数据的完整性,是数字签名的核心算法。
(1) 消息摘要算法MD
① MD
代码实现:
-
package com.timliu.security.message_digest;
-
import java.security.MessageDigest;
-
import java.security.Security;
-
import org.apache.commons.codec.binary.Hex;
-
import org.apache.commons.codec.digest.DigestUtils;
-
import org.bouncycastle.crypto.digests.MD4Digest;
-
import org.bouncycastle.crypto.digests.MD5Digest;
-
import org.bouncycastle.jce.provider.BouncyCastleProvider;
-
-
public
class MD5Test{
-
public
static
final String src =
"md5 test";
-
public static void main(String[] args){
-
jdkMD5();
-
jdkMD2();
-
bcMD4();
-
bcMD5();
-
bc2jdkMD4();
-
ccMD5();
-
ccMD2();
-
}
-
-
// 用jdk实现:MD5
-
public static void jdkMD5(){
-
try
-
{
-
MessageDigest md = MessageDigest.getInstance(
"MD5");
-
byte[] md5Bytes = md.digest(src.getBytes());
-
System.out.println(
"JDK MD5:" + Hex.encodeHexString(md5Bytes));
-
}
catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
// 用jdk实现:MD2
-
public static void jdkMD2(){
-
try
-
{
-
MessageDigest md = MessageDigest.getInstance(
"MD2");
-
byte[] md2Bytes = md.digest(src.getBytes());
-
System.out.println(
"JDK MD2:" + Hex.encodeHexString(md2Bytes));
-
}
catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
// 用bouncy castle实现:MD5
-
public static void bcMD5(){
-
MD5Digest digest =
new MD5Digest();
-
digest.update(src.getBytes(),
0,src.getBytes().length);
-
byte[] md5Bytes =
new
byte[digest.getDigestSize()];
-
digest.doFinal(md5Bytes,
0);
-
System.out.println(
"bouncy castle MD5:" + org.bouncycastle.util.encoders.Hex.toHexString(md5Bytes));
-
}
-
-
// 用bouncy castle实现:MD4
-
public static void bcMD4(){
-
MD4Digest digest =
new MD4Digest();
-
digest.update(src.getBytes(),
0,src.getBytes().length);
-
byte[] md4Bytes =
new
byte[digest.getDigestSize()];
-
digest.doFinal(md4Bytes,
0);
-
System.out.println(
"bouncy castle MD4:" + org.bouncycastle.util.encoders.Hex.toHexString(md4Bytes));
-
}
-
-
// 用bouncy castle与jdk结合实现:MD4
-
public static void bc2jdkMD4(){
-
try
-
{
-
Security.addProvider(
new BouncyCastleProvider());
-
MessageDigest md = MessageDigest.getInstance(
"MD4");
-
byte[] md4Bytes = md.digest(src.getBytes());
-
System.out.println(
"bc and JDK MD4:" + Hex.encodeHexString(md4Bytes));
-
}
catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
-
// 用common codes实现实现:MD5
-
public static void ccMD5(){
-
System.out.println(
"common codes MD5:" + DigestUtils.md5Hex(src.getBytes()));
-
}
-
-
// 用common codes实现实现:MD2
-
public static void ccMD2(){
-
System.out.println(
"common codes MD2:" + DigestUtils.md2Hex(src.getBytes()));
-
}
-
}
② MD算法应用
(2) 消息散列算法 SHA
① 安全散列算法,固定长度摘要信息(SHA-1,SHA-2)
② 具体的代码:
-
package com.timliu.security.message_digest;
-
import java.security.MessageDigest;
-
import java.security.Security;
-
import org.apache.commons.codec.binary.Hex;
-
import org.apache.commons.codec.digest.DigestUtils;
-
import org.bouncycastle.crypto.Digest;
-
import org.bouncycastle.crypto.digests.SHA1Digest;
-
import org.bouncycastle.crypto.digests.SHA224Digest;
-
import org.bouncycastle.jce.provider.BouncyCastleProvider;
-
import java.io.UnsupportedEncodingException;
-
import java.math.BigInteger;
-
-
public
class SHATest{
-
public
static
final String src =
"sha test";
-
public static void main(String[] args) throws Exception
-
{
-
jdkSHA1();
-
bcSHA1();
-
bcSHA224();
-
bcSHA224b();
-
generateSha256();
-
ccSHA1();
-
}
-
-
// 用jdk实现:SHA1
-
public static void jdkSHA1(){
-
try{
-
MessageDigest md = MessageDigest.getInstance(
"SHA");
-
md.update(src.getBytes());
-
System.out.println(
"jdk sha-1:" + Hex.encodeHexString(md.digest()));
-
}
catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
-
// 用bouncy castle实现:SHA1
-
public static void bcSHA1()
-
{
-
Digest digest =
new SHA1Digest();
-
digest.update(src.getBytes(),
0, src.getBytes().length );
-
byte[] sha1Bytes =
new
byte[digest.getDigestSize()];
-
digest.doFinal(sha1Bytes,
0);
-
System.out.println(
"bc sha-1:" + org.bouncycastle.util.encoders.Hex.toHexString(sha1Bytes));
-
}
-
-
-
// 用bouncy castle实现:SHA224
-
public static void bcSHA224(){
-
Digest digest =
new SHA224Digest();
-
digest.update(src.getBytes(),
0, src.getBytes().length );
-
byte[] sha224Bytes =
new
byte[digest.getDigestSize()];
-
digest.doFinal(sha224Bytes,
0);
-
System.out.println(
"bc sha-224:" + org.bouncycastle.util.encoders.Hex.toHexString(sha224Bytes));
-
}
-
-
// 用bouncy castle与jdk结合实现:SHA224
-
public static void bcSHA224b(){
-
try{
-
Security.addProvider(
new BouncyCastleProvider());
-
MessageDigest md = MessageDigest.getInstance(
"SHA224");
-
md.update(src.getBytes());
-
System.out.println(
"bc and JDK sha-224:" + Hex.encodeHexString(md.digest()));
-
}
catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
-
public static void generateSha256() throws Exception {
-
MessageDigest md = MessageDigest.getInstance(
"SHA-256");
-
md.update(src.getBytes(
"UTF-8"));
// Change this to "UTF-16" if needed
-
byte[] digest = md.digest();
-
BigInteger bigInt =
new BigInteger(
1, digest);
-
System.out.println(
"Sha256 hash: " + bigInt.toString(
16));
-
}
-
-
// 用common codes实现实现:SHA1
-
public static void ccSHA1(){
-
System.out.println(
"common codes SHA1 - 1 :" + DigestUtils.sha1Hex(src.getBytes()));
-
System.out.println(
"common codes SHA1 - 2 :" + DigestUtils.sha1Hex(src));
-
}
-
}
③ SHA典型应用
(3) 散列消息鉴别码MAC
① 也称HMAC,含有密钥的散列函数算法。
②
HMAC
代码实现
-
package com.timliu.security.message_digest;
-
import javax.crypto.KeyGenerator;
-
import javax.crypto.Mac;
-
import javax.crypto.SecretKey;
-
import javax.crypto.spec.SecretKeySpec;
-
import org.apache.commons.codec.binary.Hex;
-
import org.bouncycastle.crypto.digests.MD5Digest;
-
import org.bouncycastle.crypto.macs.HMac;
-
import org.bouncycastle.crypto.params.KeyParameter;
-
-
public
class HMACTest {
-
public
static
final String src =
"hmac test";
-
public static void main(String[] args) {
-
jdkHmacMD5();
-
bcHmacMD5();
-
}
-
-
// 用jdk实现:
-
public static void jdkHmacMD5(){
-
try{
-
// 初始化KeyGenerator
-
KeyGenerator keyGenerator = KeyGenerator.getInstance(
"HmacMD5");
-
// 产生密钥
-
SecretKey secretKey = keyGenerator.generateKey();
-
// 获取密钥
-
// byte[] key = secretKey.getEncoded();
-
byte[] key = Hex.decodeHex(
new
char[]{
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'a',
'b',
'c',
'd',
'e' });
-
-
// 还原密钥
-
SecretKey restoreSecretKey =
new SecretKeySpec(key,
"HmacMD5");
-
// 实例化MAC
-
Mac mac = Mac.getInstance(restoreSecretKey.getAlgorithm());
-
// 初始化MAC
-
mac.init(restoreSecretKey);
-
// 执行摘要
-
byte[] hmacMD5Bytes = mac.doFinal(src.getBytes());
-
System.out.println(
"jdk hmacMD5:" + Hex.encodeHexString(hmacMD5Bytes));
-
-
}
catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
-
// 用bouncy castle实现:
-
public static void bcHmacMD5(){
-
HMac hmac =
new HMac(
new MD5Digest());
-
// 必须是16进制的字符,长度必须是2的倍数
-
hmac.init(
new KeyParameter(org.bouncycastle.util.encoders.Hex.decode(
"123456789abcde")));
-
hmac.update(src.getBytes(),
0, src.getBytes().length);
-
// 执行摘要
-
byte[] hmacMD5Bytes =
new
byte[hmac.getMacSize()];
-
hmac.doFinal(hmacMD5Bytes,
0);
-
System.out.println(
"bc hmacMD5:" + org.bouncycastle.util.encoders.Hex.toHexString(hmacMD5Bytes));
-
}
-
}
③
HMAC
典型应用
(4) Base64,MD,SHA,HMAC的区别和联系:
BASE64 编码算法不算是真正的加密算法。
MD5、SHA、HMAC这三种加密算法,可谓是非可逆加密,就是不可解密的加密方法,我们称之为单向加密算法。我们通常只把他们作为加密的基础。单纯的以上三种的加密并不可靠。
BASE64
按照RFC2045的定义,Base64被定义为:Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式。(The Base64 Content-Transfer-Encoding is designed to represent arbitrary sequences of octets in a form that need not be humanly readable.) 常见于邮件、http加密,截取http信息,你就会发现登录操作的用户名、密码字段通过BASE64加密的。
MD5
MD5 -- message-digest algorithm 5 (信息-摘要算法)缩写,广泛用于加密和解密技术,常用于文件校验。校验?不管文件多大,经过MD5后都能生成唯一的MD5值。好比现在的ISO校验,都是MD5校验。怎么用?当然是把ISO经过MD5后产生MD5的值。一般下载Linux-ISO的朋友都见过下载链接旁边放着MD5的串。就是用来验证文件是否一致的。
SHA
SHA(Secure Hash Algorithm,安全散列算法),数字签名等密码学应用中重要的工具,被广泛地应用于电子商务等信息安全领域。虽然,SHA与MD5通过碰撞法都被破解了, 但是SHA仍然是公认的安全加密算法,较之MD5更为安全。
HMAC
HMAC(Hash Message Authentication Code,散列消息鉴别码,基于密钥的Hash算法的认证协议。消息鉴别码实现鉴别的原理是,用公开函数和密钥产生一个固定长度的值作为认证标识,用这个标识鉴别消息的完整性。使用一个密钥生成一个固定大小的小数据块,即MAC,并将其加入到消息中,然后传输。接收方利用与发送方共享的密钥进行鉴别认证等。
说明:
BASE64的加密解密是双向的,可以求反解。
MD5、SHA以及HMAC是单向加密,任何数据加密后只会产生唯一的一个加密串,通常用来校验数据在传输过程中是否被修改。其中HMAC算法有一个密钥,增强了数据传输过程中的安全性,强化了算法外的不可控因素。单向加密的用途主要是为了校验数据在传输过程中是否被修改。
3.Java实现对称加密
(1) 简介
对称加密指加密和解密使用相同密钥的加密算法。接下来我们一起来学习DES、3DES、AES和PBE几种常见的对称加密算法在Java中的实现,以及他们的应用范围。
(2) 对称加密算法DES:数据加密标准,由美国国家标准研究所研发,由于已经破解,在现在的开发当中已经不在使用。
(3) 对称加密算法3DES:
效率低,安全机制还是不佳,所以出现了AES。
(4) 对称加密算法AES
① 代码实现:
-
package com.timliu.security.symmetric_encryption;
-
import java.security.Key;
-
import java.security.Security;
-
import javax.crypto.Cipher;
-
import javax.crypto.KeyGenerator;
-
import javax.crypto.SecretKey;
-
import javax.crypto.spec.SecretKeySpec;
-
import org.apache.commons.codec.binary.Hex;
-
import org.bouncycastle.jce.provider.BouncyCastleProvider;
-
-
public
class AESTest {
-
public
static
final String src =
"aes test";
-
public static void main(String[] args) {
-
jdkAES();
-
bcAES();
-
}
-
-
// 用jdk实现:
-
public static void jdkAES(){
-
try {
-
// 生成KEY
-
KeyGenerator keyGenerator = KeyGenerator.getInstance(
"AES");
-
keyGenerator.init(
128);
-
// 产生密钥
-
SecretKey secretKey = keyGenerator.generateKey();
-
// 获取密钥
-
byte[] keyBytes = secretKey.getEncoded();
-
// KEY转换
-
Key key =
new SecretKeySpec(keyBytes,
"AES");
-
// 加密
-
Cipher cipher = Cipher.getInstance(
"AES/ECB/PKCS5Padding");
-
cipher.init(Cipher.ENCRYPT_MODE, key);
-
byte[] result = cipher.doFinal(src.getBytes());
-
System.out.println(
"jdk aes encrypt:" + Hex.encodeHexString(result));
-
// 解密
-
cipher.init(Cipher.DECRYPT_MODE, key);
-
result = cipher.doFinal(result);
-
System.out.println(
"jdk aes decrypt:" +
new String(result));
-
}
catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
-
// 用bouncy castle实现:
-
public static void bcAES(){
-
try {
-
Security.addProvider(
new BouncyCastleProvider());
-
// 生成KEY
-
KeyGenerator keyGenerator = KeyGenerator.getInstance(
"AES",
"BC");
-
keyGenerator.getProvider();
-
keyGenerator.init(
128);
-
// 产生密钥
-
SecretKey secretKey = keyGenerator.generateKey();
-
// 获取密钥
-
byte[] keyBytes = secretKey.getEncoded();
-
// KEY转换
-
Key key =
new SecretKeySpec(keyBytes,
"AES");
-
// 加密
-
Cipher cipher = Cipher.getInstance(
"AES/ECB/PKCS5Padding");
-
cipher.init(Cipher.ENCRYPT_MODE, key);
-
byte[] result = cipher.doFinal(src.getBytes());
-
System.out.println(
"bc aes encrypt:" + Hex.encodeHexString(result));
-
// 解密
-
cipher.init(Cipher.DECRYPT_MODE, key);
-
result = cipher.doFinal(result);
-
System.out.println(
"bc aes decrypt:" +
new String(result));
-
}
catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
}
② 实现原理:
(5) 对称加密算法PBE
PBE算法结合了摘要算法和对称加密算法的优点。
PBE(Passworld Based Encryption)基于口令加密,对已有算法进行包装,不是一种新的算法。
① 代码实现:
-
package com.timliu.security.symmetric_encryption;
-
import java.security.Key;
-
import java.security.SecureRandom;
-
import javax.crypto.Cipher;
-
import javax.crypto.SecretKeyFactory;
-
import javax.crypto.spec.PBEKeySpec;
-
import javax.crypto.spec.PBEParameterSpec;
-
import org.apache.commons.codec.binary.Hex;
-
-
public
class PBETest {
-
public
static
final String src =
"pbe test";
-
public static void main(String[] args) {
-
jdkPBE();
-
}
-
// 用jdk实现:
-
public static void jdkPBE(){
-
try {
-
// 初始化盐
-
SecureRandom random =
new SecureRandom();
-
byte[] salt = random.generateSeed(
8);
-
// 口令与密钥
-
String password =
"timliu";
-
PBEKeySpec pbeKeySpec =
new PBEKeySpec(password.toCharArray());
-
SecretKeyFactory factory = SecretKeyFactory.getInstance(
"PBEWITHMD5andDES");
-
Key key = factory.generateSecret(pbeKeySpec);
-
// 加密
-
PBEParameterSpec pbeParameterSpac =
new PBEParameterSpec(salt,
100);
-
Cipher cipher = Cipher.getInstance(
"PBEWITHMD5andDES");
-
cipher.init(Cipher.ENCRYPT_MODE, key, pbeParameterSpac);
-
byte[] result = cipher.doFinal(src.getBytes());
-
System.out.println(
"jdk pbe encrypt:" + Hex.encodeHexString(result));
-
// 解密
-
cipher.init(Cipher.DECRYPT_MODE, key, pbeParameterSpac);
-
result = cipher.doFinal(result);
-
System.out.println(
"jdk pbe decrypt:" +
new String(result));
-
}
catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
}
②
实现原理
4.Java实现非对称加密
(1) 简介
非对称加密算法是一种基于密钥的保密方法,需要公开密钥和私有密钥,在文件加密、尤其是网银中应用广泛。本课程主要介绍非对称加密算法的实现过程,DH、RSA和ELGamal等几种常见的非对称加密算法的在Java中的应用。
(2) DH 密钥交换算法
① 实现过程
② 实现代码:
-
package com.timliu.security.asymmetric_encryption;
-
import java.security.KeyFactory;
-
import java.security.KeyPair;
-
import java.security.KeyPairGenerator;
-
import java.security.PrivateKey;
-
import java.security.PublicKey;
-
import java.security.spec.X509EncodedKeySpec;
-
import java.util.Objects;
-
import javax.crypto.Cipher;
-
import javax.crypto.KeyAgreement;
-
import javax.crypto.SecretKey;
-
import javax.crypto.interfaces.DHPublicKey;
-
import javax.crypto.spec.DHParameterSpec;
-
import org.apache.commons.codec.binary.Base64;
-
public
class DHTest {
-
public
static
final String src =
"dh test";
-
public static void main(String[] args) {
-
jdkDH();
-
}
-
// jdk实现:
-
public static void jdkDH(){
-
try {
-
// 1.初始化发送方密钥
-
KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance(
"DH");
-
senderKeyPairGenerator.initialize(
512);
-
KeyPair senderKeyPair = senderKeyPairGenerator.generateKeyPair();
-
// 发送方公钥,发送给接收方(网络、文件。。。)
-
byte[] senderPublicKeyEnc = senderKeyPair.getPublic().getEncoded();
-
-
// 2.初始化接收方密钥
-
KeyFactory receiverKeyFactory = KeyFactory.getInstance(
"DH");
-
X509EncodedKeySpec x509EncodedKeySpec =
new X509EncodedKeySpec(senderPublicKeyEnc);
-
PublicKey receiverPublicKey = receiverKeyFactory.generatePublic(x509EncodedKeySpec);
-
DHParameterSpec dhParameterSpec = ((DHPublicKey) receiverPublicKey).getParams();
-
KeyPairGenerator receiverKeyPairGenerator = KeyPairGenerator.getInstance(
"DH");
-
receiverKeyPairGenerator.initialize(dhParameterSpec);
-
KeyPair receiverKeypair = receiverKeyPairGenerator.generateKeyPair();
-
PrivateKey receiverPrivateKey = receiverKeypair.getPrivate();
-
byte[] receiverPublicKeyEnc = receiverKeypair.getPublic().getEncoded();
-
-
// 3.密钥构建
-
KeyAgreement receiverKeyAgreement = KeyAgreement.getInstance(
"DH");
-
receiverKeyAgreement.init(receiverPrivateKey);
-
receiverKeyAgreement.doPhase(receiverPublicKey,
true);
-
SecretKey receiverDesKey = receiverKeyAgreement.generateSecret(
"DES");
-
-
KeyFactory senderKeyFactory = KeyFactory.getInstance(
"DH");
-
x509EncodedKeySpec =
new X509EncodedKeySpec(receiverPublicKeyEnc);
-
PublicKey senderPublicKey = senderKeyFactory.generatePublic(x509EncodedKeySpec);
-
KeyAgreement senderKeyAgreement = KeyAgreement.getInstance(
"DH");
-
senderKeyAgreement.init(senderKeyPair.getPrivate());
-
senderKeyAgreement.doPhase(senderPublicKey,
true);
-
SecretKey senderDesKey = senderKeyAgreement.generateSecret(
"DES");
-
if(Objects.equals(receiverDesKey, senderDesKey)){
-
System.out.println(
"双方密钥相同。");
-
}
-
-
// 4.加密
-
Cipher cipher = Cipher.getInstance(
"DES");
-
cipher.init(Cipher.ENCRYPT_MODE, senderDesKey);
-
byte[] result = cipher.doFinal(src.getBytes());
-
System.out.println(
"bc dh encrypt:" + Base64.encodeBase64String(result));
-
-
// 5.解密
-
cipher.init(Cipher.DECRYPT_MODE, receiverDesKey);
-
result = cipher.doFinal(result);
-
System.out.println(
"bc dh decrypt:" +
new String(result));
-
}
catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
}
③ 实现原理
(3) RSA-基于因子分解
① 特点:
① 特点:
唯一广泛接受并实现
数据加密&数字签名
公钥加密,私钥解密
私钥加密,公钥解密
优点使用简单,缺点使用效率较低,但现在最广泛应用。
② 实现代码:
-
package com.timliu.security.asymmetric_encryption;
-
import java.security.KeyFactory;
-
import java.security.KeyPair;
-
import java.security.KeyPairGenerator;
-
import java.security.PrivateKey;
-
import java.security.PublicKey;
-
import java.security.interfaces.RSAPrivateKey;
-
import java.security.interfaces.RSAPublicKey;
-
import java.security.spec.PKCS8EncodedKeySpec;
-
import java.security.spec.X509EncodedKeySpec;
-
import javax.crypto.Cipher;
-
import org.apache.commons.codec.binary.Base64;
-
-
public
class RSATest {
-
public
static
final String src =
"rsa test";
-
public static void main(String[] args) {
-
jdkRSA();
-
}
-
// jdk实现:
-
public static void jdkRSA(){
-
try {
-
// 1.初始化发送方密钥
-
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
"RSA");
-
keyPairGenerator.initialize(
512);
-
KeyPair keyPair = keyPairGenerator.generateKeyPair();
-
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
-
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
-
System.out.println(
"Public Key:" + Base64.encodeBase64String(rsaPublicKey.getEncoded()));
-
System.out.println(
"Private Key:" + Base64.encodeBase64String(rsaPrivateKey.getEncoded()));
-
-
// 2.私钥加密、公钥解密 ---- 加密
-
PKCS8EncodedKeySpec pkcs8EncodedKeySpec =
new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
-
KeyFactory keyFactory = KeyFactory.getInstance(
"RSA");
-
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
-
Cipher cipher = Cipher.getInstance(
"RSA");
-
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
-
byte[] result = cipher.doFinal(src.getBytes());
-
System.out.println(
"私钥加密、公钥解密 ---- 加密:" + Base64.encodeBase64String(result));
-
-
// 3.私钥加密、公钥解密 ---- 解密
-
X509EncodedKeySpec x509EncodedKeySpec =
new X509EncodedKeySpec(rsaPublicKey.getEncoded());
-
keyFactory = KeyFactory.getInstance(
"RSA");
-
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
-
cipher = Cipher.getInstance(
"RSA");
-
cipher.init(Cipher.DECRYPT_MODE, publicKey);
-
result = cipher.doFinal(result);
-
System.out.println(
"私钥加密、公钥解密 ---- 解密:" +
new String(result));
-
-
// 4.公钥加密、私钥解密 ---- 加密
-
X509EncodedKeySpec x509EncodedKeySpec2 =
new X509EncodedKeySpec(rsaPublicKey.getEncoded());
-
KeyFactory keyFactory2 = KeyFactory.getInstance(
"RSA");
-
PublicKey publicKey2 = keyFactory2.generatePublic(x509EncodedKeySpec2);
-
Cipher cipher2 = Cipher.getInstance(
"RSA");
-
cipher2.init(Cipher.ENCRYPT_MODE, publicKey2);
-
byte[] result2 = cipher2.doFinal(src.getBytes());
-
System.out.println(
"公钥加密、私钥解密 ---- 加密:" + Base64.encodeBase64String(result2));
-
-
// 5.私钥解密、公钥加密 ---- 解密
-
PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 =
new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
-
KeyFactory keyFactory5 = KeyFactory.getInstance(
"RSA");
-
PrivateKey privateKey5 = keyFactory5.generatePrivate(pkcs8EncodedKeySpec5);
-
Cipher cipher5 = Cipher.getInstance(
"RSA");
-
cipher5.init(Cipher.DECRYPT_MODE, privateKey5);
-
byte[] result5 = cipher5.doFinal(result2);
-
System.out.println(
"公钥加密、私钥解密 ---- 解密:" +
new String(result5));
-
}
catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
}
③ 实现原理
(4) ElGamal-基于离散对数
只有公钥加密算法,只由BC提供。
只有公钥加密算法,只由BC提供。
5.Java实现数字签名:
(1) 数字签名算法概述
签名
数字签名:带有密钥(公钥,私钥)的消息摘要算法,验证数据的完整性,认证数据的来源,抗否认。
OSI参考模型
私钥签名,公钥验签
数字签名的几种算法:RSA,DSA,ECDSA
(2) 数字签名算法 RSA
① 主要分为两类:MD 和 SHA两类。
② 代码执行过程和具体的代码:
a. 初始化密钥
b. 执行签名(私钥)
c. 验证签名(公钥)
-
import java.security.KeyFactory;
-
import java.security.KeyPair;
-
import java.security.KeyPairGenerator;
-
import java.security.PrivateKey;
-
import java.security.PublicKey;
-
import java.security.Signature;
-
import java.security.interfaces.RSAPrivateKey;
-
import java.security.interfaces.RSAPublicKey;
-
import java.security.spec.PKCS8EncodedKeySpec;
-
import java.security.spec.X509EncodedKeySpec;
-
import org.apache.commons.codec.binary.Hex;
-
-
public
class ImoocRSA {
-
private
static String src =
"imooc security rsa";
-
public static void main(String[] args) {
-
jdkRSA();
-
}
-
public static void jdkRSA() {
-
try {
-
//1.初始化密钥
-
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
"RSA");
-
keyPairGenerator.initialize(
512);
-
KeyPair keyPair = keyPairGenerator.generateKeyPair();
-
RSAPublicKey rsaPublicKey = (RSAPublicKey)keyPair.getPublic();
-
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey)keyPair.getPrivate();
-
-
//2.执行签名
-
PKCS8EncodedKeySpec pkcs8EncodedKeySpec =
new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
-
KeyFactory keyFactory = KeyFactory.getInstance(
"RSA");
-
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
-
Signature signature = Signature.getInstance(
"MD5withRSA");
-
signature.initSign(privateKey);
-
signature.update(src.getBytes());
-
byte[] result = signature.sign();
-
System.out.println(
"jdk rsa sign : " + Hex.encodeHexString(result));
-
//3.验证签名
-
X509EncodedKeySpec x509EncodedKeySpec =
new X509EncodedKeySpec(rsaPublicKey.getEncoded());
-
keyFactory = KeyFactory.getInstance(
"RSA");
-
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
-
signature = Signature.getInstance(
"MD5withRSA");
-
signature.initVerify(publicKey);
-
signature.update(src.getBytes());
-
boolean bool = signature.verify(result);
-
System.out.println(
"jdk rsa verify : " + bool);
-
}
catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
}
③ 流程图
(3) 数字签名算法 DSA
① 与RSA签名的区别:DSA仅仅包括数字签名,没办法进行加密通信,但RSA都可以实现。
① 与RSA签名的区别:DSA仅仅包括数字签名,没办法进行加密通信,但RSA都可以实现。
② DSA算法实现:和RSA步骤相同,只是一小部分的代码不同而已。
-
import java.security.KeyFactory;
-
import java.security.KeyPair;
-
import java.security.KeyPairGenerator;
-
import java.security.PrivateKey;
-
import java.security.PublicKey;
-
import java.security.Signature;
-
import java.security.interfaces.DSAPrivateKey;
-
import java.security.interfaces.DSAPublicKey;
-
import java.security.spec.PKCS8EncodedKeySpec;
-
import java.security.spec.X509EncodedKeySpec;
-
import org.apache.commons.codec.binary.Hex;
-
-
public
class ImoocDSA {
-
private
static String src =
"imooc security dsa";
-
public static void main(String[] args) {
-
jdkDSA();
-
}
-
public static void jdkDSA() {
-
try {
-
//1.初始化密钥
-
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
"DSA");
-
keyPairGenerator.initialize(
512);
-
KeyPair keyPair = keyPairGenerator.generateKeyPair();
-
DSAPublicKey dsaPublicKey = (DSAPublicKey) keyPair.getPublic();
-
DSAPrivateKey dsaPrivateKey = (DSAPrivateKey)keyPair.getPrivate();
-
-
//2.执行签名
-
PKCS8EncodedKeySpec pkcs8EncodedKeySpec =
new PKCS8EncodedKeySpec(dsaPrivateKey.getEncoded());
-
KeyFactory keyFactory = KeyFactory.getInstance(
"DSA");
-
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
-
Signature signature = Signature.getInstance(
"SHA1withDSA");
-
signature.initSign(privateKey);
-
signature.update(src.getBytes());
-
byte[] result = signature.sign();
-
System.out.println(
"jdk dsa sign : " + Hex.encodeHexString(result));
-
-
//3.验证签名
-
X509EncodedKeySpec x509EncodedKeySpec =
new X509EncodedKeySpec(dsaPublicKey.getEncoded());
-
keyFactory = KeyFactory.getInstance(
"DSA");
-
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
-
signature = Signature.getInstance(
"SHA1withDSA");
-
signature.initVerify(publicKey);
-
signature.update(src.getBytes());
-
boolean bool = signature.verify(result);
-
System.out.println(
"jdk dsa verify : " + bool);
-
}
catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
}
③ 流程图:和RSA数字签名一样。
(4) 数字签名算法ECDSA
① 微软的,在JDK1.7之后使用,椭圆曲线数字签名算法,具有速度快,强度高,签名短的特点。
② EC 算法实现:和RSA步骤相同,知识一小部分的代码不同而已。
-
import java.security.KeyFactory;
-
import java.security.KeyPair;
-
import java.security.KeyPairGenerator;
-
import java.security.NoSuchAlgorithmException;
-
import java.security.PrivateKey;
-
import java.security.PublicKey;
-
import java.security.Signature;
-
import java.security.interfaces.ECPrivateKey;
-
import java.security.interfaces.ECPublicKey;
-
import java.security.spec.PKCS8EncodedKeySpec;
-
import java.security.spec.X509EncodedKeySpec;
-
import org.apache.commons.codec.binary.Hex;
-
-
public
class ImoocECDSA {
-
private
static String src =
"imooc security ecdsa";
-
public static void main(String[] args) {
-
jdkECDSA();
-
}
-
public static void jdkECDSA() {
-
try {
-
//1.初始化密钥
-
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
"EC");
-
keyPairGenerator.initialize(
256);
-
KeyPair keyPair = keyPairGenerator.generateKeyPair();
-
ECPublicKey ecPublicKey = (ECPublicKey)keyPair.getPublic();
-
ECPrivateKey ecPrivateKey = (ECPrivateKey)keyPair.getPrivate();
-
-
//2.执行签名
-
PKCS8EncodedKeySpec pkcs8EncodedKeySpec =
new PKCS8EncodedKeySpec(ecPrivateKey.getEncoded());
-
KeyFactory keyFactory = KeyFactory.getInstance(
"EC");
-
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
-
Signature signature = Signature.getInstance(
"SHA1withECDSA");
-
signature.initSign(privateKey);
-
signature.update(src.getBytes());
-
byte[] result = signature.sign();
-
System.out.println(
"jdk ecdsa sign : " + Hex.encodeHexString(result));
-
-
//3.验证签名
-
X509EncodedKeySpec x509EncodedKeySpec =
new X509EncodedKeySpec(ecPublicKey.getEncoded());
-
keyFactory = KeyFactory.getInstance(
"EC");
-
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
-
signature = Signature.getInstance(
"SHA1withECDSA");
-
signature.initVerify(publicKey);
-
signature.update(src.getBytes());
-
boolean bool = signature.verify(result);
-
System.out.println(
"jdk ecdsa verify : " + bool);
-
}
catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
}
(3) 流程图:和RSA DSA数字签名一样。
若想通过代码更好的理解以上内容,请:
https://github.com/luomingkui/java_security