1.Base64编码算法

Base64简介

Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。可查看RFC2045~RFC2049,上面有MIME的详细规范。

Base64编码是从二进制到字符的过程,可用于在HTTP环境下传递较长的标识信息。例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码具有不可读性,需要解码后才能阅读。

码表

索引 编码 索引 编码 索引 编码 索引 编码
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w
15 P 32 g 49 x
16 Q 33 h 50 y

特点:加密原理简单

Base64实现

一般的来说加密数据需要使用到如下三个包

JDK:java.security

CC: Commons Codec

BC: Bouncy Castle

JDK实现

JDK 1.7写法

//加密
public static String jdkBase64Encoder(String str){
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(str.getBytes());
}
//解密
public static String jdkBase64decoder(String str) throws IOException {
BASE64Decoder decoder = new BASE64Decoder();
return new String(decoder.decodeBuffer(str));
}
//调用
public static void main(String[] args) throws IOException {
System.out.println("原始字符串: " + BASE_STRING);
String enStr = jdkBase64Encoder(BASE_STRING);
System.out.println("Base64编码后: " + enStr);
String deStr = jdkBase64decoder(enStr);
System.out.println("Base64解码后: "+deStr);
}

结果

原始字符串: security base64

Base64编码后: c2VjdXJpdHkgYmFzZTY0

Base64解码后: security base64

JDK1.8+写法

public static String jdkBase64Encoder(String str){
String desc = Base64.getEncoder().encodeToString(str.getBytes(StandardCharsets.UTF_8));
System.out.println("加密后的字符串为:"+desc);
} public static String jdkBase64decoder(String str) throws IOException {
String unDecodeStr=new String(Base64.getDecoder().decode(str),StandardCharsets.UTF_8);
System.out.println("解密后的字符串为"+unDecodeStr);
}

Commons Codec实现

CC包的写法是简化了许多,类似JDK1.8的写法。

MAVEN依赖

<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
import org.apache.commons.codec.binary.Base64;

import java.io.IOException;

/**
* CommonCodec Base64
* @author yanlong
*/
public class CCBase64 {
private static final String BASE_STRING ="security base64"; public static void main(String[] args) throws IOException {
System.out.println("原始字符串: " + BASE_STRING);
byte[] encStr = Base64.encodeBase64(BASE_STRING.getBytes());
System.out.println("Base64编码后: " + new String(encStr));
String deStr = new String(Base64.encodeBase64(encStr));
System.out.println("Base64解码后: "+deStr);
}
}

Bouncy Castle实现

MAVEN依赖

<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.55</version>
</dependency>
import org.bouncycastle.util.encoders.Base64;

public class BCBase64 {
private static final String BASE_STRING ="security base64"; public static void main(String[] args) {
System.out.println("原始字符串: " + BASE_STRING);
byte[] encStr = Base64.encode(BASE_STRING.getBytes());
System.out.println("Base64编码后: " + new String(encStr));
String deStr = new String(Base64.decode(encStr));
System.out.println("Base64解码后: "+deStr); }
}

BC的调用代码相较于CC和JDK更少了。

2.消息摘要算法(Message-Digest Algorithm)及其实现

MD算法简介

消息摘要算法的主要特征是加密过程不需要密钥,并且经过加密的数据无法被解密,只有输入相同的明文数据经过相同的消息摘要算法才能得到相同的密文。消息摘要算法不存在密钥的管理与分发问题,适合于分布式网络上使用。由于其加密计算的工作量相当巨大,所以以前的这种算法通常只用于数据量有限的情况下的加密,例如计算机的口令就是用不可逆加密算法加密的。近年来,随着计算机性能的飞速改善,加密速度不再成为限制这种加密技术发展的桎梏,因而消息摘要算法应用的领域不断增加。

消息摘要算法主要应用在数字签名领域,作为对明文的摘要算法。著名的摘要算法有RSA公司的MD5算法和SHA-1算法及其大量的变体。

特点:单向加密,长度统一

MD算法实现

一般的加密算法实现通过两个包实现

JDK:java.security

BC: Bouncy Castle

1.MD2

public static void jdkMD2(String str) throws NoSuchAlgorithmException {
MessageDigest messageDigest = MessageDigest.getInstance("MD2");
byte[] enStr = messageDigest.digest(str.getBytes());
//将二进制转换为16进制输出
System.out.println("JDK的MD2摘要:"+new String(Hex.encodeHex(enStr)));
}

2.MD4

public static void BCMD4(String str) throws NoSuchAlgorithmException {
Digest digest = new MD4Digest();
byte[] b = str.getBytes();
digest.update(b,0,b.length);
byte[] enStr = new byte[digest.getDigestSize()];
digest.doFinal(enStr,0);
//将二进制转换为16禁止输出
System.out.println("B C的MD4摘要:"+new String(org.bouncycastle.util.encoders.Hex.toHexString(enStr)));
}

3.MD5

BC实现

public static void BCMD5(String str) throws NoSuchAlgorithmException {
Digest digest = new MD5Digest();
byte[] b = str.getBytes();
digest.update(b,0,b.length);
byte[] enStr = new byte[digest.getDigestSize()];
digest.doFinal(enStr,0);
//将二进制转换为16禁止输出
System.out.println("B C的MD5摘要:"+new String(org.bouncycastle.util.encoders.Hex.toHexString(enStr)));
}

JDK实现

public static void jdkMD5(String str) throws NoSuchAlgorithmException {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
byte[] enStr = messageDigest.digest(str.getBytes());
//将二进制转换为16进制输出
System.out.println("JDK的MD5摘要:"+Hex.encodeHex(enStr));
}

调用

public static void main(String[] args) throws NoSuchAlgorithmException {
BCMD4(BASE_STRING);
BCMD5(BASE_STRING);
jdkMD2(BASE_STRING);
jdkMD5(BASE_STRING);
}

结果

B C的MD4摘要:28427b7d90e25002467da60396b79a94

B C的MD5摘要:6ddee10117cee5ef77cae7e747385ee2

JDK的MD2摘要:3cce751973fd1c6957b4d60bbf0d9153

JDK的MD5摘要:6ddee10117cee5ef77cae7e747385ee2

4.SHA

一般的加密算法实现通过两个包实现

JDK:java.security

BC: Bouncy Castle

CC一般是对JDK简化操作

SHA-1

JDK实现

public static void jdkSHA1(String str) throws NoSuchAlgorithmException {
MessageDigest messageDigest = MessageDigest.getInstance("SHA");
byte[] enStr = messageDigest.digest(str.getBytes());
//将二进制转换为16进制输出
System.out.println("JDK的SHA摘要:"+new String(Hex.encodeHex(enStr)));
}

BC实现

public static void BCSHA1(String str) throws NoSuchAlgorithmException {
Digest digest = new SHA1Digest();
byte[] b = str.getBytes();
digest.update(b,0,b.length);
byte[] enStr = new byte[digest.getDigestSize()];
digest.doFinal(enStr,0);
//将二进制转换为16禁止输出
System.out.println("B C的SHA1摘要:"+new String(org.bouncycastle.util.encoders.Hex.toHexString(enStr)));
}

CC实现

public static void CCSHA1(String str){
String enStr = DigestUtils.sha1Hex(BASE_STRING.getBytes());
System.out.println("C C的SHA1摘要:"+enStr); }
SHA224

BC单独实现

public static void BCSHA224(String str) throws NoSuchAlgorithmException {
Digest digest = new SHA224Digest();
byte[] b = str.getBytes();
digest.update(b,0,b.length);
byte[] enStr = new byte[digest.getDigestSize()];
digest.doFinal(enStr,0);
//将二进制转换为16禁止输出
System.out.println("B C的SHA224摘要:"+new String(org.bouncycastle.util.encoders.Hex.toHexString(enStr)));
}

JDK实现与BC配合实现

public static void jdkAndBCSHA224(String str) throws NoSuchAlgorithmException {
Security.addProvider(new BouncyCastleProvider());
MessageDigest messageDigest = MessageDigest.getInstance("SHA224");
byte[] enStr = messageDigest.digest(str.getBytes());
//将二进制转换为16禁止输出
System.out.println("JDK+BC的SHA224摘要:"+new String(Hex.encodeHex(enStr)));
}

调用

public static void main(String[] args) throws NoSuchAlgorithmException {
jdkSHA1(BASE_STRING);
BCSHA1(BASE_STRING);
CCSHA1(BASE_STRING);
BCSHA224(BASE_STRING);
jdkAndBCSHA224(BASE_STRING);
}

结果

JDK的SHA1摘要:4a6db077ec2ea85697bfe5e97feffed7616dda96

B C的SHA1摘要:4a6db077ec2ea85697bfe5e97feffed7616dda96

C C的SHA1摘要:4a6db077ec2ea85697bfe5e97feffed7616dda96

B C的SHA224摘要 :f86ded290c11f45253ba0a47c30a23ab7121721e76f8dc071aee98cc

JDK+BC的SHA224摘要:f86ded290c11f45253ba0a47c30a23ab7121721e76f8dc071aee98cc

MAC 加秘钥的摘要算法

JDK实现

public static void jdkHmacMD5(String str) throws Exception {
//初始化 KeyGenerator
KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacMD5");
//生成秘钥
SecretKey secretKey = keyGenerator.generateKey();
//获取秘钥
byte[] key = secretKey.getEncoded(); //还原秘钥
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "HmacMD5");
//获取mac实例 初始化MAC
Mac mac = Mac.getInstance(secretKeySpec.getAlgorithm());
mac.init(secretKey);
//执行摘要算法
byte[] encBytes = mac.doFinal(str.getBytes());
System.out.println(Hex.toHexString(encBytes));
}

BC实现

public static void BCHmacMD5(String str){

    HMac hMac = new HMac(new MD5Digest());
hMac.init(new KeyParameter(Hex.decode("aaaaaaaaaa")));
hMac.update(str.getBytes(),0,str.getBytes().length);
byte[] hmacMD5 = new byte[hMac.getMacSize()];
hMac.doFinal(hmacMD5,0);
System.out.println(Hex.toHexString(hmacMD5)); }

3.对称加密算法(Symmetric-key algorithm)

对称加密算法(Symmetric-key algorithm)简介

对称加密算法是应用较早的加密算法,技术成熟。在对称加密算法中,数据发信方将明文(原始数据)和加密密钥一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。收信方收到密文后,若想解读原文,则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密,才能使其恢复成可读明文。在对称加密算法中,使用的密钥只有一个,发收信双方都使用这个密钥对数据进行加密和解密,这就要求解密方事先必须知道加密密钥。

对称加密(也叫私钥加密)指加密和解密使用相同密钥的加密算法。有时又叫传统密码算法,就是加密密钥能够从解密密钥中推算出来,同时解密密钥也可以从加密密钥中推算出来。而在大多数的对称算法中,加密密钥和解密密钥是相同的,所以也称这种加密算法为秘密密钥算法或单密钥算法。它要求发送方和接收方在安全通信之前,商定一个密钥。对称算法的安全性依赖于密钥,泄漏密钥就意味着任何人都可以对他们发送或接收的消息解密,所以密钥的保密性对通信的安全性至关重要。

特点:解密加密使用相同秘钥,计算量小,算法简单,加密效率高

对称加密算法实现

DES加密 (不安全)

Jdk实现DES

public static void jdkDES(String str) throws Exception {
//系统自动生成key
byte[] key = KeyGenerator.getInstance("DES").generateKey().getEncoded(); //转换秘钥
DESKeySpec desKeySpec = new DESKeySpec(key);
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
Key convertSecretKey = secretKeyFactory.generateSecret(desKeySpec); //加密
//加密模式 DES
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
//初始化加密工具
cipher.init(Cipher.ENCRYPT_MODE,convertSecretKey);
byte[] enBytes = cipher.doFinal(str.getBytes());
//展示
System.out.println("Jdk DES Encrypt:"+ Hex.toHexString(enBytes)); //解密
cipher.init(Cipher.DECRYPT_MODE,convertSecretKey);
byte[] deBytes = cipher.doFinal(enBytes);
System.out.println("Jdk DES Decrypt:"+new String(deBytes)); }

BC实现DES

public static void BCDES(String str) throws Exception {
//向JDK中添加算法
Security.addProvider(new BouncyCastleProvider());
//系统自动生成key
byte[] key = KeyGenerator.getInstance("DES").generateKey().getEncoded(); //转换秘钥
DESKeySpec desKeySpec = new DESKeySpec(key);
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
Key convertSecretKey = secretKeyFactory.generateSecret(desKeySpec); //加密
//加密模式 DES
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
//初始化加密工具
cipher.init(Cipher.ENCRYPT_MODE,convertSecretKey);
byte[] enBytes = cipher.doFinal(str.getBytes());
//展示
System.out.println("Jdk DES Encrypt:"+ Hex.toHexString(enBytes)); //解密
cipher.init(Cipher.DECRYPT_MODE,convertSecretKey);
byte[] deBytes = cipher.doFinal(enBytes);
System.out.println("Jdk DES Decrypt:"+new String(deBytes)); }

TripleDES(三重DES)

JDK实现

public static void  jdkTripleDES(String str) throws Exception{
//系统自动生成key
KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
//依据算法自定义Key长度 init(168);
keyGenerator.init(new SecureRandom());
byte[] key = keyGenerator.generateKey().getEncoded(); //转换秘钥
DESedeKeySpec desKeySpec = new DESedeKeySpec(key);
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DESede");
Key convertSecretKey = secretKeyFactory.generateSecret(desKeySpec); //加密
//加密模式 DES
Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
//初始化加密工具
cipher.init(Cipher.ENCRYPT_MODE,convertSecretKey);
byte[] enBytes = cipher.doFinal(str.getBytes());
//展示
System.out.println("Jdk TripleDES Encrypt:"+ Hex.toHexString(enBytes)); //解密
cipher.init(Cipher.DECRYPT_MODE,convertSecretKey);
byte[] deBytes = cipher.doFinal(enBytes);
System.out.println("Jdk TripleDES Decrypt:"+new String(deBytes));
}

BC+JDK实现

public static void  BCTripleDES(String str) throws Exception{
Security.addProvider(new BouncyCastleProvider());
//系统自动生成key
KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
//依据算法自定义Key长度 init(168);
keyGenerator.init(new SecureRandom());
byte[] key = keyGenerator.generateKey().getEncoded(); //转换秘钥
DESedeKeySpec desKeySpec = new DESedeKeySpec(key);
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DESede");
Key convertSecretKey = secretKeyFactory.generateSecret(desKeySpec); //加密
//加密模式 DES
Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
//初始化加密工具
cipher.init(Cipher.ENCRYPT_MODE,convertSecretKey);
byte[] enBytes = cipher.doFinal(str.getBytes());
//展示
System.out.println("BC+Jdk TripleDES Encrypt:"+ Hex.toHexString(enBytes)); //解密
cipher.init(Cipher.DECRYPT_MODE,convertSecretKey);
byte[] deBytes = cipher.doFinal(enBytes);
System.out.println("BC+Jdk TripleDES Decrypt:"+new String(deBytes));
}

AES加密

AES加密及其解密需要的参数



AES加密流程

public static void jdkAES(String str) throws Exception {
//系统自动生成key
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);
byte[] key = keyGenerator.generateKey().getEncoded(); //转换秘钥
Key convertSecretKey = new SecretKeySpec(key, "AES"); //加密
//加密模式 DES
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
//初始化加密工具
cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);
byte[] enBytes = cipher.doFinal(str.getBytes());
//展示
System.out.println("Jdk DES Encrypt:" + Hex.toHexString(enBytes)); //解密
cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);
byte[] deBytes = cipher.doFinal(enBytes);
System.out.println("Jdk DES Decrypt:" + new String(deBytes));
}

BC+JDK实现类似于DES的方式

PBE(Password Based Encryption)加密

PBE(Password Based Encryption,基于口令加密)是一种基于口令的加密算法,其特点是使用口令代替了密钥,而口令由用户自己掌管,采用随机数杂凑多重加密等方法保证数据的安全性。PBE算法在加密过程中并不是直接使用口令来加密,而是加密的密钥由口令生成,这个功能由PBE算法中的KDF函数完成。KDF函数的实现过程为:将用户输入的口令首先通过“盐”(salt)的扰乱产生准密钥,再将准密钥经过散列函数多次迭代后生成最终加密密钥,密钥生成后,PBE算法再选用对称加密算法对数据进行加密,可以选择DES、3DES、RC5等对称加密算法。

常用加密方式



加密流程

JDK实现

/**
* 基于口令的对称加密算法PBE
*/
public class PBE { private static final String BASE_STRING ="security PBETest"; private static final String BASE_PWD="security Pwd"; public static void main(String[] args) throws Exception {
jdkPBE(BASE_STRING); } public static void jdkPBE(String str) throws Exception {
//初始化盐
SecureRandom random = new SecureRandom();
byte[] salt = random.generateSeed(8); //口令于秘钥
PBEKeySpec pbeKeySpec = new PBEKeySpec(BASE_PWD.toCharArray());
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWITHMD5andDES");
Key key = factory.generateSecret(pbeKeySpec); //加密
PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(salt,100);
Cipher cipher = Cipher.getInstance("PBEWITHMD5andDES");
cipher.init(Cipher.ENCRYPT_MODE,key,pbeParameterSpec);
byte[] enBytes = cipher.doFinal(str.getBytes());
System.out.println("JDK PBE 加密:"+ Base64.encodeBase64String(enBytes)); cipher.init(Cipher.DECRYPT_MODE,key,pbeParameterSpec);
byte[] deBytes = cipher.doFinal(enBytes);
System.out.println("JDK PBE 解密:"+new String(deBytes));
}
}

其他实现方式只需修改加密方式

4.非对称加密算法

非对称加密算法简介

非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。 非对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将其中的一把作为公用密钥向其它方公开;得到该公用密钥的乙方使用该密钥对机密信息进行加密后再发送给甲方;甲方再用自己保存的另一把专用密钥对加密后的信息进行解密。

另一方面,甲方可以使用乙方的公钥对机密信息进行签名后再发送给乙方;乙方再用自己的私匙对数据进行验签。

甲方只能用其专用密钥解密由其公用密钥加密后的任何信息。 非对称加密算法的保密性比较好,它消除了最终用户交换密钥的需要。

非对称密码体制的特点:算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快。对称密码体制中只有一种密钥,并且是非公开的,如果要解密就得让对方知道密钥。所以保证其安全性就是保证密钥的安全,而非对称密钥体制有两种密钥,其中一个是公开的,这样就可以不需要像对称密码那样传输对方的密钥了。这样安全性就大了很多。

特点:加密等级高,传输安全

非对称加密算法实现

DH秘钥交换算法

解决对称加密传输安全的问题、构建本地秘钥。

秘钥长度 默认 工作模式 填充方式 实现方
512~1024位 1024位 JDK
流程

1.发送方构建公钥私钥。

2.发送方发布发送方公钥。

3.接收方接收发送方公钥构建接收方公钥私钥。

4.接收方发布接收方公钥。

5.发送方通过发送方的私钥和接收方的公钥构建对称加密秘钥用于加密。

6.接收方通过接收方的私钥和发送方的公钥构建对称加密秘钥用于解密。

7.发送方通过秘钥加密数据并发送。

8.接收方接收数据并通过秘钥解密数据。

1.初始化发送方秘钥

  • KeyPairGenerator 生成Keypair
  • KeyPair 秘钥对(公钥 私钥)
  • Publickey 公钥

2.初始化接收方秘钥

  • KeyFactory 生成秘钥
  • X509EncodedKeySpec 根据ASN.1进行编码 按照某种规范生成秘钥
  • DHPublicKey DH公钥
  • DHParameterSpec DH参数集合
  • KeyGenerator
  • PricateKey 私钥

3.秘钥构建

  • KeyAgreement 秘钥提供协议
  • SecretKey 秘密秘钥对称秘钥 生成分组秘密秘钥
  • KeyFactory
  • X509EncodedKeySpec
  • Publickey

4.加密、解密

  • Cipher 加密解密提供密码功能 JCE核心
//流程实现
public static void jdkDHFlow() throws Exception {
//1.发送方构建公钥私钥
KeyPair senderKeyPair = jdkSenderPublicKey();
//2.发送方发布公钥
byte[] senderPublicKeyEncode = senderKeyPair.getPublic().getEncoded();
//3.接收方构建公钥私钥->接收方通过发送方公钥构建公钥私钥
KeyPair receiverKeyPair = jdkreceiverPublicKey(senderPublicKeyEncode);
//4.接收方发布公钥
byte[] receiverPublicKeyEncode = receiverKeyPair.getPublic().getEncoded();
//5.发送方构建对称加密的秘钥->依据接收方公钥和自己的公钥私钥构建
SecretKey senderDesKey = jdkGetSecretKey(senderKeyPair,receiverPublicKeyEncode);
//6.接收方构建对称加密秘钥->依据发送方公钥和接收方公钥私钥构建
SecretKey receiverDesKey = jdkGetSecretKey(receiverKeyPair,senderPublicKeyEncode);
//对比双方对称加密秘钥是否安相同 查看是否测试成功
if(Objects.equals(receiverDesKey,senderDesKey)){
System.out.println("双方秘钥相同");
}
//7.发送方加密
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE,senderDesKey);
byte[] result = cipher.doFinal(BASE_STRING.getBytes());
System.out.println("JDK DH 加密:"+ Base64.encodeBase64String(result));
//8.接收方解密
cipher.init(Cipher.DECRYPT_MODE,receiverDesKey);
result = cipher.doFinal(result);
System.out.println("JDK DH 解密:"+new String(result));
} /**
* 发送方构建发送方公钥
* @return 构建完成的公钥
*/
public static KeyPair jdkSenderPublicKey() throws NoSuchAlgorithmException {
//1.初始化发送方秘钥
KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance("DH");
senderKeyPairGenerator.initialize(512);
//生成秘钥
KeyPair senderKeyPair = senderKeyPairGenerator.generateKeyPair();
return senderKeyPair;
} /**
* 依据发送方公钥生成接收方公钥
* @param senderPublicKey 发送方公钥
* @return 接收方公钥
*/
public static KeyPair jdkreceiverPublicKey(byte[] senderPublicKey) throws Exception {
KeyFactory receiverKeyFactory = KeyFactory.getInstance("DH");
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(senderPublicKey);
PublicKey receiverPublicKey = receiverKeyFactory.generatePublic(x509EncodedKeySpec);
//使用和发送方一样的参数初始化
DHParameterSpec dhParameterSpec = ((DHPublicKey) receiverPublicKey).getParams();
KeyPairGenerator receiverKeyPairGenerator = KeyPairGenerator.getInstance("DH");
//发送方公钥解析出来的dhParameterSpec
receiverKeyPairGenerator.initialize(dhParameterSpec);
KeyPair receiverKeyPair = receiverKeyPairGenerator.generateKeyPair();
return receiverKeyPair;
} /**
* 自己的公钥私钥与对方的公钥构建 对称秘钥
* @param keyPair 自己秘钥对
* @param publicKey 对方公钥
* @return 本地对称加密秘钥
*/
public static SecretKey jdkGetSecretKey(KeyPair keyPair,byte[] publicKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("DH");
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey);
PublicKey senderPublicKey = keyFactory.generatePublic(x509EncodedKeySpec);
KeyAgreement keyAgreement = KeyAgreement.getInstance("DH");
keyAgreement.init(keyPair.getPrivate());
keyAgreement.doPhase(senderPublicKey,true);
SecretKey secretKey = keyAgreement.generateSecret("DES");
return secretKey;
}

RSA因子分解算法

唯一广泛接受的实现类型

数字加密&数字签名

公钥加密 私钥解密

私钥加密 公钥解密

工作实现以及填充模式

加解密流程

package asymmetrickeyencryption;

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

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec; /**
* 大数因子分解 64的整数倍
*/
public class RSA { private static final String BASE_STRING = "security DHTest"; public static void main(String[] args) throws Exception {
jdkRSA(); } public static void jdkRSA() throws Exception {
//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("RSAPublicKey:" + Base64.encodeBase64String(rsaPublicKey.getEncoded()));
System.out.println("RSAPrivateKey:" + 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(BASE_STRING.getBytes());
System.out.println("JDK RSA 私钥加密:" + Base64.encodeBase64String(result));
//公钥解密
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
KeyFactory keyFactory1 = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
Cipher cipher1 = Cipher.getInstance("RSA");
cipher1.init(Cipher.DECRYPT_MODE, publicKey);
result = cipher1.doFinal(result);
System.out.println("JDK RSA 公钥解密:" + new String(result)); //3 公钥加密
x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
keyFactory = KeyFactory.getInstance("RSA");
publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
result = cipher.doFinal(BASE_STRING.getBytes());
System.out.println("JDK RSA 公钥加密:" + Base64.encodeBase64String(result)); //私钥解密
pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
keyFactory = KeyFactory.getInstance("RSA");
privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
result = cipher.doFinal(result);
System.out.println("JDK RSA 私钥解密:" + new String(result)); } }

ELGamal离散对数加密算法

工作实现以及填充模式

加解密流程

秘钥的构建

public static void BCElGamal() throws Exception {
//添加bc加密工具
Security.addProvider(new BouncyCastleProvider());
//生成秘钥
AlgorithmParameterGenerator algorithmParameterGenerator = AlgorithmParameterGenerator.getInstance("ElGamal");
algorithmParameterGenerator.init(256);
AlgorithmParameters algorithmParameters = algorithmParameterGenerator.generateParameters();
DHParameterSpec dhParameterSpec = algorithmParameters.getParameterSpec(DHParameterSpec.class);
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ElGamal");
keyPairGenerator.initialize(dhParameterSpec,new SecureRandom());
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
System.out.println("ElGamal 公钥:" + Base64.encodeBase64String(publicKey.getEncoded()));
System.out.println("ElGamal 私钥:" + Base64.encodeBase64String(privateKey.getEncoded())); }

加密解密方式与RSA相同

数字签名

数字签名(又称公钥数字签名、电子签章)是一种类似写在纸上的普通的物理签名,但是使用了公钥加密领域的技术实现,用于鉴别数字信息的方法。一套数字签名通常定义两种互补的运算,一个用于签名,另一个用于验证。

数字签名,就是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。

数字签名是非对称密钥加密技术与数字摘要技术的应用。

特点: 数据完整性验证、认证数据来源、抗否认等

RSA算法

加解密流程

仅仅实现签名 验签

public static void jdkRSA() throws  Exception{
//初始化秘钥
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(512);
KeyPair keyPair =keyPairGenerator.generateKeyPair();
RSAPublicKey rsaPublicKey = (RSAPublicKey)keyPair.getPublic();
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey)keyPair.getPrivate(); //执行签名
//用私钥签名
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(BASE_STRING.getBytes());
byte[] result = signature.sign();
System.out.println("JDK RSA 签名:"+ Hex.toHexString(result)); //用公钥验签
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
signature = Signature.getInstance("MD5withRSA");
signature.initVerify(publicKey);
signature.update(BASE_STRING.getBytes());
boolean res = signature.verify(result);
System.out.println("JDK RSA 验签:"+res);
}

DSA算法

DSA 算法和RSA算法完全相似

public static void DSA() throws Exception{
//创建秘钥
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA");
keyPairGenerator.initialize(512);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
DSAPublicKey dsaPublicKey = (DSAPublicKey) keyPair.getPublic();
DSAPrivateKey dsaPrivateKey = (DSAPrivateKey) keyPair.getPrivate(); //签名
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(BASE_STRING.getBytes());
byte[] result = signature.sign();
System.out.println("JDK DSA 签名:"+ Base64.encodeBase64String(result)); //验签
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(dsaPublicKey.getEncoded());
keyFactory = KeyFactory.getInstance("DSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
signature = Signature.getInstance("SHA1withDSA");
signature.initVerify(publicKey);
signature.update(BASE_STRING.getBytes());
boolean res = signature.verify(result);
System.out.println("JDK DSA 验签是否通过:"+res);
}

ECDSA算法(椭圆曲线数字签名算法)

速度快、强度高、签名短的特点;

序列号验证算法

加解密流程


public static void jdkECDSA() throws Exception{
//生成秘钥
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
keyPairGenerator.initialize(256);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
ECPublicKey ecPublicKey = (ECPublicKey) keyPair.getPublic();
ECPrivateKey ecPrivateKey = (ECPrivateKey) keyPair.getPrivate(); //签名
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(ecPrivateKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("EC");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Signature signature = Signature.getInstance("SHA256withECDSA");
signature.initSign(privateKey);
signature.update(BASE_STRING.getBytes());
byte[] result = signature.sign();
System.out.println("JDK ECDSA 签名:"+ Base64.encodeBase64String(result)); //验签
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(ecPublicKey.getEncoded());
keyFactory = KeyFactory.getInstance("EC");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
signature = Signature.getInstance("SHA256withECDSA");
signature.initVerify(publicKey);
signature.update(BASE_STRING.getBytes());
boolean res = signature.verify(result);
System.out.println("JDK ECDSA 验签结果:"+res); }

加密技术的应用--数字签名RSA版本

三方支付系统签名验证流程

甲方传输一段报文给乙方

甲方发送操作:

  1. 甲方 组织报文
  2. 使用甲方私钥签名报文(摘要算法)
  3. 将报文和签名合并
  4. 使用乙方公钥将合并后的数据加密(非对称加密)
  5. 传输到乙方

乙方接收操作:

  1. 使用乙方私钥将加密数据打开 (非对称加密)
  2. 分开报文和签名
  3. 使用甲方公钥重新签名报文(摘要算法)
  4. 验证乙方签名后的报文和甲方传输的报文是否一样
  5. 如果一样接收数据成功

源码

https://github.com/yanlong300/security/

Java中加密算法介绍及其实现的更多相关文章

  1. java中异常介绍

    一.异常概述 异常处理已经成为衡量一门语言是否成熟的标准之一,目前的主流编程语言如C++.C#.Ruby.Python等,大都提供了异常处理机制.增加了异常处理机制后的程序有更好的容错性,更加健壮. ...

  2. JAVA中数组介绍

    一.数组: 数组指一组数据的集合,数组中的每个数据被称作元素. 二.数组定义: 数组类型[] 数组名 = new 数组类型[元素个数或数组长度]: (注意:等号前面的[]里面不能写任何东西) 也可以以 ...

  3. Java中常用七个阻塞队列的总结

    Java队列总结 通过前面文章的学习,我们对Java中常用队列做了介绍.本文,咱们来对队列做个总结吧. 首先,我们介绍了现实生活中的实际场景(排队买票等),来告诉我们为什么需要使用队列. 队列是一种先 ...

  4. [转]详细介绍java中的数据结构

    详细介绍java中的数据结构 本文介绍的是java中的数据结构,本文试图通过简单的描述,向读者阐述各个类的作用以及如何正确使用这些类.一起来看本文吧! 也许你已经熟练使用了java.util包里面的各 ...

  5. 详细介绍java中的数据结构

    详细介绍java中的数据结构 http://developer.51cto.com/art/201107/273003.htm 本文介绍的是java中的数据结构,本文试图通过简单的描述,向读者阐述各个 ...

  6. Java 中UDP原理机制及实现方式介绍(建议阅读者阅读前了解下Java的基础知识,一方便理解)

    1.基本概念介绍: 首先得简单介绍下UDP. UDP( User Datagram Protocol )协议是用户数据报,在网络中它与TCP协议一样用于处理数据包.在OSI模型中,在第四层——传输层, ...

  7. 字符编码介绍及java中的应用

    字符编码,就是对日常的控制符号.文字和常用符号的二进制表示.为了准确的表示如何编号,怎么生产八位字节流,Unicode Technical Report (UTR) #17提出现代编码模型的5个层次: ...

  8. Java中常见的5种WEB服务器介绍

    这篇文章主要介绍了Java中常见的5种WEB服务器介绍,它们分别是Tomcat.Resin.JBoss.WebSphere.WebLogic,需要的朋友可以参考下 Web服务器是运行及发布Web应用的 ...

  9. 第八节:详细讲解Java中的异常处理情况与I/O流的介绍以及类集合框架

    前言 大家好,给大家带来详细讲解Java中的异常处理情况与I/O流的介绍以及类集合框架的概述,希望你们喜欢 JAVA 异常 try...catch...finally结构的使用方法 class Tes ...

随机推荐

  1. 2018acm-icpc宁夏邀请赛后记

    由于要准备期末考试的缘故,时隔一个月之后我才想起来还有一场比赛没有总结. 大概是出去过的最远的地方了,宁夏理工学院离杭州有两千多千米. 不得不说感到了主办方满满的诚意,虽然是第一次办比赛,但是第一天组 ...

  2. grafana配置

    grafana配置 官网介绍:http://docs.grafana.org/installation/configuration/ 以deb或者rpm安装的,则默认的配置文件是/etc/grafan ...

  3. urllib.parse.quote

    sklearn实战-乳腺癌细胞数据挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId=1005269003& ...

  4. JavaSE学习总结(八)—— 异常处理(Exception)

    一.理解异常及异常处理的概念 异常就是在程序的运行过程中所发生的不正常的事件,它会中断正在运行的程序. 异常不是错误 程序中关键的位置有异常处理,提高程序的稳定性 二.掌握Java异常处理机制 Jav ...

  5. UVALive 4725 Airport(二分)

    题目链接 题意 机场有两种飞机,每小时一些飞机到达,每小时安排一架飞机起航.求任意时刻中两种飞机数目的最大值的最小值. 分析 首先肯定是二分来做.这里的难点在于如何判断飞机数目是否合法.一开始忽略了某 ...

  6. Linux 命令详解(七)Systemd 入门教程:命令篇

    Systemd 入门教程:命令篇http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-commands.html

  7. 地图上道路编号中的G S X Y

    地图上道路中的G S X Y Z C D,分别表示什么道? 国道 省道 县道 乡道 专用道路 村道 D: 还没有搞明白

  8. PB9.0数据窗口入门

    因为工作的关系,最近公司用PB比较多,至少10年没用过PB了,回顾一下数据窗口使用方法.1.代码结构 2.数据窗口 3.代码窗口代码 APP入口代码 4.需要使用DataBase插入一条数据 5.执行 ...

  9. utf8_bin跟utf8_general_ci的区别

    ci是 case insensitive, 即 "大小写不敏感", a 和 A 会在字符判断中会被当做一样的; bin 是二进制, a 和 A 会别区别对待. 例如你运行: SEL ...

  10. DHCP服务洪水攻击

    1.攻击原理 动态主机设置协议是一个局域网的网络协议,使用UDP协议工作,主要有两个用途: 为内部网络或网络服务供应商自动分配IP地址给用户,以作为内部网络管理员对所有计算机做中央管理的手段. 在正常 ...