Base64是网络上最多见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。可查看RFC2045~RFC2049,上面有MIME的详细规范。html
Base64编码是从二进制到字符的过程,可用于在HTTP环境下传递较长的标识信息。例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的惟一标识符(通常为128-bit的UUID)编码为一个字符串,用做HTTP表单和HTTP GET URL中的参数。在其余应用程序中,也经常须要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码具备不可读性,须要解码后才能阅读。java
码表git
索引 | 编码 | 索引 | 编码 | 索引 | 编码 | 索引 | 编码 |
---|---|---|---|---|---|---|---|
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 |
特色:加密原理简单github
通常的来讲加密数据须要使用到以下三个包
JDK:java.security
CC: Commons Codec
BC: Bouncy Castle算法
JDK 1.7写法apache
//加密 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); }
CC包的写法是简化了许多,相似JDK1.8的写法。
MAVEN依赖dom
<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); } }
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更少了。
消息摘要算法的主要特征是加密过程不须要密钥,而且通过加密的数据没法被解密,只有输入相同的明文数据通过相同的消息摘要算法才能获得相同的密文。消息摘要算法不存在密钥的管理与分发问题,适合于分布式网络上使用。因为其加密计算的工做量至关巨大,因此之前的这种算法一般只用于数据量有限的状况下的加密,例如计算机的口令就是用不可逆加密算法加密的。近年来,随着计算机性能的飞速改善,加密速度再也不成为限制这种加密技术发展的桎梏,于是消息摘要算法应用的领域不断增长。
消息摘要算法主要应用在数字签名领域,做为对明文的摘要算法。著名的摘要算法有RSA公司的MD5算法和SHA-1算法及其大量的变体。
特色:单向加密,长度统一
通常的加密算法实现经过两个包实现
JDK:java.security
BC: Bouncy Castle
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))); }
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))); }
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
通常的加密算法实现经过两个包实现
JDK:java.security
BC: Bouncy Castle
CC通常是对JDK简化操做
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); }
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
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)); }
对称加密算法是应用较早的加密算法,技术成熟。在对称加密算法中,数据发信方将明文(原始数据)和加密密钥一块儿通过特殊加密算法处理后,使其变成复杂的加密密文发送出去。收信方收到密文后,若想解读原文,则须要使用加密用过的密钥及相同算法的逆算法对密文进行解密,才能使其恢复成可读明文。在对称加密算法中,使用的密钥只有一个,发收信双方都使用这个密钥对数据进行加密和解密,这就要求解密方事先必须知道加密密钥。
对称加密(也叫私钥加密)指加密和解密使用相同密钥的加密算法。有时又叫传统密码算法,就是加密密钥可以从解密密钥中推算出来,同时解密密钥也能够从加密密钥中推算出来。而在大多数的对称算法中,加密密钥和解密密钥是相同的,因此也称这种加密算法为秘密密钥算法或单密钥算法。它要求发送方和接收方在安全通讯以前,商定一个密钥。对称算法的安全性依赖于密钥,泄漏密钥就意味着任何人均可以对他们发送或接收的消息解密,因此密钥的保密性对通讯的安全性相当重要。
特色:解密加密使用相同秘钥,计算量小,算法简单,加密效率高
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)); }
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加密流程
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算法在加密过程当中并非直接使用口令来加密,而是加密的密钥由口令生成,这个功能由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)); } }
其余实现方式只需修改加密方式
非对称加密算法须要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,若是用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;若是用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。由于加密和解密使用的是两个不一样的密钥,因此这种算法叫做非对称加密算法。 非对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将其中的一把做为公用密钥向其它方公开;获得该公用密钥的乙方使用该密钥对机密信息进行加密后再发送给甲方;甲方再用本身保存的另外一把专用密钥对加密后的信息进行解密。
另外一方面,甲方可使用乙方的公钥对机密信息进行签名后再发送给乙方;乙方再用本身的私匙对数据进行验签。
甲方只能用其专用密钥解密由其公用密钥加密后的任何信息。 非对称加密算法的保密性比较好,它消除了最终用户交换密钥的须要。
非对称密码体制的特色:算法强度复杂、安全性依赖于算法与密钥可是因为其算法复杂,而使得加密解密速度没有对称加密解密的速度快。对称密码体制中只有一种密钥,而且是非公开的,若是要解密就得让对方知道密钥。因此保证其安全性就是保证密钥的安全,而非对称密钥体制有两种密钥,其中一个是公开的,这样就能够不须要像对称密码那样传输对方的密钥了。这样安全性就大了不少。
特色:加密等级高,传输安全
解决对称加密传输安全的问题、构建本地秘钥。
秘钥长度 | 默认 | 工做模式 | 填充方式 | 实现方 |
---|---|---|---|---|
512~1024位 | 1024位 | 无 | 无 | JDK |
1.发送方构建公钥私钥。
2.发送方发布发送方公钥。
3.接收方接收发送方公钥构建接收方公钥私钥。
4.接收方发布接收方公钥。
5.发送方经过发送方的私钥和接收方的公钥构建对称加密秘钥用于加密。
6.接收方经过接收方的私钥和发送方的公钥构建对称加密秘钥用于解密。
7.发送方经过秘钥加密数据并发送。
8.接收方接收数据并经过秘钥解密数据。
1.初始化发送方秘钥
2.初始化接收方秘钥
3.秘钥构建
4.加密、解密
//流程实现 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; }
惟一普遍接受的实现类型
数字加密&数字签名
公钥加密 私钥解密
私钥加密 公钥解密
工做实现以及填充模式
加解密流程
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)); } }
工做实现以及填充模式
加解密流程
秘钥的构建
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相同
数字签名(又称公钥数字签名、电子签章)是一种相似写在纸上的普通的物理签名,可是使用了公钥加密领域的技术实现,用于鉴别数字信息的方法。一套数字签名一般定义两种互补的运算,一个用于签名,另外一个用于验证。
数字签名,就是只有信息的发送者才能产生的别人没法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证实。
数字签名是非对称密钥加密技术与数字摘要技术的应用。
特色: 数据完整性验证、认证数据来源、抗否定等
加解密流程
仅仅实现签名 验签
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 算法和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); }
速度快、强度高、签名短的特色;
序列号验证算法
加解密流程
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); }
三方支付系统签名验证流程
甲方传输一段报文给乙方
甲方发送操做:
乙方接收操做:
https://github.com/yanlong300/security/