通过JAVA代码实现数据加密,数据验签,对称加密,非对称加密;
一、Base64
Base64编码的作用:由于某些系统中只能使用ASCII字符。Base64就是用来将非ASCII字符的数据转换成ASCII字符的一种方法。它使用下面表中所使用的字符与编码。
而且base64特别适合在Http,mime协议下快速传输数据。
Base64原理,比如: a b
1、先转换为asill码:97 98
2、然后将asill码转换为8位数的二进制: 01100001 01100010
3、将8位数的二进制转换为6位数的一组的(不足6位后面补0);011000(Y) 010110(W) 001oo(I)(后两个00位为补的)
4、将转换为6位一组的二进制转换为64进制的(完) :YWI
1 public static void base64Test() throws Exception { 2 String src = "ab"; 3 4 // Base64加码 5 byte[] en = Base64.getEncoder().encode(src.getBytes("UTF-8")); 6 7 // Base64解码 8 byte[] de = Base64.getDecoder().decode(en); 9 10 System.out.println(new String(en, "UTF-8")); // YWI= 11 System.out.println(new String(de, "UTF-8")); // ab 12 }
二、消息摘要算法
1.MD5 ;2.SHA ;3.MAC
1 // MD5的实现代码 2 public static void md5Test() throws Exception { 3 String src = "abc"; 4 5 // 用jdk实现:MD5 6 MessageDigest md = MessageDigest.getInstance("MD5"); 7 byte[] md5Bytes = md.digest(src.getBytes("UTF-8")); 8 9 // (16进制字符串)和字节数组的互转[Hex类位于Apache的commons-codec包中] 10 System.out.println("JDK MD5:" + Hex.encodeHexString(md5Bytes)); 11 12 // 用common-codes实现实现:MD5 13 System.out.println("common-codes MD5:" + DigestUtils.md5Hex(src.getBytes())); 14 } 15 16 17 // SHA1的实现代码 18 public static void sha1Test() throws Exception { 19 String src = "abc"; 20 21 // 用jdk实现:SHA1 22 MessageDigest md = MessageDigest.getInstance("SHA"); 23 md.update(src.getBytes()); 24 System.out.println("jdk sha-1:" + Hex.encodeHexString(md.digest())); 25 26 // 用common codes实现实现:SHA1 27 System.out.println("common codes SHA1 - 1 :" + DigestUtils.sha1Hex(src.getBytes())); 28 System.out.println("common codes SHA1 - 2 :" + DigestUtils.sha1Hex(src)); 29 }
三、数字签名
1.RSA ;2.DSA; 3.ECDSA
用于防止数据串改,但传输中过程是明文;
1 /** 2 * MD5withRSA数字签名 3 * 4 * 或简单的方式也可通过MD5或sha-1对传输数据进行签名; 5 * 6 */ 7 public static void signTest() throws Exception { 8 String src = "abc"; 9 10 // 1.初始化密钥 11 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); 12 keyPairGenerator.initialize(512); 13 KeyPair keyPair = keyPairGenerator.generateKeyPair(); 14 RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic(); 15 RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate(); 16 17 // 将密钥字符串化 18 String privateKeyStr = encodeBase64Str(rsaPrivateKey.getEncoded()); 19 System.out.println("输出私钥-可自己保存用于加签:" + privateKeyStr); 20 String publicKeyStr = encodeBase64Str(rsaPublicKey.getEncoded()); 21 System.out.println("输出公钥-可发送对方用于验签:" + publicKeyStr); 22 23 // 2.私钥进行签名(发送端) 24 byte[] dePrivateKey = decodeBase64(privateKeyStr); // 对应 rsaPrivateKey.getEncoded() 25 26 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(dePrivateKey); 27 KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 28 PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); 29 Signature signature = Signature.getInstance("MD5withRSA"); 30 signature.initSign(privateKey); 31 signature.update(src.getBytes()); 32 byte[] result = signature.sign(); 33 System.out.println("jdk rsa sign:" + Hex.encodeHexString(result)); 34 35 // 3.公钥验证签名(接收端) 36 byte[] dePublicKey = decodeBase64(publicKeyStr);// 对应 rsaPublicKey.getEncoded() 37 38 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(dePublicKey); 39 keyFactory = KeyFactory.getInstance("RSA"); 40 PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec); 41 signature = Signature.getInstance("MD5withRSA"); 42 signature.initVerify(publicKey); 43 signature.update(src.getBytes()); 44 boolean bool = signature.verify(result); 45 System.out.println("jdk rsa verify:" + bool); 46 }
四、对称加密算法
1.3DES; 2.AES; 3.PBE
对称加密特点:只有一个密钥
1 /** 2 * AES对称加密算法。 AES的ECB模式 3 * 4 * @throws Exception 5 */ 6 public static void aesTest1() throws Exception { 7 8 String src = "abc"; 9 10 /** 11 * 生产密钥 12 */ 13 KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); 14 keyGenerator.init(128); 15 SecretKey secretKey = keyGenerator.generateKey(); 16 // 获取密钥 17 byte[] keyBytes = secretKey.getEncoded(); 18 // 将密钥字符串化 19 String secretKeyStr = encodeBase64Str(keyBytes); 20 System.out.println("输出密钥-保存:" + secretKeyStr); 21 22 /** 23 * 加密和解密可共用部分 24 */ 25 byte[] keyBytes_1 = decodeBase64(secretKeyStr); // keyBytes_1 等于 keyBytes 26 // 设置加密或解密模式为AES的ECB模式 27 Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); 28 // KEY转换 29 Key key = new SecretKeySpec(keyBytes_1, "AES"); 30 31 // 加密 32 cipher.init(Cipher.ENCRYPT_MODE, key); 33 byte[] result = cipher.doFinal(src.getBytes()); 34 System.out.println("jdk aes encrypt:" + Hex.encodeHexString(result)); 35 36 // 解密 37 cipher.init(Cipher.DECRYPT_MODE, key); 38 result = cipher.doFinal(result); 39 System.out.println("jdk aes decrypt:" + new String(result)); 40 } 41 42 /** 43 * AES对称加密:AES的CBC模式 44 * @throws Exception 45 */ 46 public static void aesTest2() throws Exception { 47 Charset UTF8 = StandardCharsets.UTF_8; 48 String src = "abc"; 49 50 /** 51 * 生产密钥 52 */ 53 KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); 54 keyGenerator.init(128); 55 SecretKey secretKey = keyGenerator.generateKey(); 56 // 获取密钥 57 byte[] keyBytes = secretKey.getEncoded(); 58 // 将密钥字符串化 59 String secretKeyStr = encodeBase64Str(keyBytes); 60 System.out.println("输出密钥保存:" + secretKeyStr); 61 62 63 /** 64 * 加密和解密可共用部分 65 */ 66 byte[] keyBytes_1 = decodeBase64(secretKeyStr); //keyBytes_1 等于 keyBytes 67 // 算法/模式/补码方式 68 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 69 // KEY转换 70 Key key = new SecretKeySpec(keyBytes_1, "AES"); 71 // 使用CBC模式,需要一个向量iv,可增加加密算法的强度 72 IvParameterSpec iv = new IvParameterSpec(keyBytes_1, 0, 16); 73 74 75 // 加密 76 cipher.init(Cipher.ENCRYPT_MODE, key, iv); 77 byte[] result = cipher.doFinal(src.getBytes(UTF8)); 78 String encryptStr = encodeBase64Str(result); 79 System.out.println("jdk-aes-encrypt:" + encryptStr); 80 81 82 // 解密 83 cipher.init(Cipher.DECRYPT_MODE, key, iv); 84 byte[] result_2 = cipher.doFinal(decodeBase64(encryptStr)); 85 System.out.println("jdk-aes-decrypt:" + new String(result_2, UTF8)); 86 87 88 /** 89 * 提示: 90 * AES 128/192/256 JDK默认使用的AES算法最高只能支持128位 如果使用192或256位的密钥, 91 * 需要无政策限制文件(UnlimitedStrength Jurisdiction Policy Files) 92 */ 93 }
五、非对称加密算法
1.DH ;2.RSA; 3.ElGamal
特点:有两个密钥:公钥和私钥
1 /** 2 * RSA非对称加密(有2个密钥:公钥和私有) 3 * @throws Exception 4 */ 5 public static void rsaTest() throws Exception { 6 String src = "abc"; 7 8 // 1.初始化发送方密钥 9 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); 10 keyPairGenerator.initialize(512); 11 KeyPair keyPair = keyPairGenerator.generateKeyPair(); 12 RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic(); 13 RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate(); 14 15 String privateKeyStr = encodeBase64Str(rsaPrivateKey.getEncoded()); 16 String publicKeyStr = encodeBase64Str(rsaPublicKey.getEncoded()); 17 System.out.println("Public Key:" + publicKeyStr); 18 System.out.println("Private Key:" + privateKeyStr); 19 20 // 2.私钥加密、公钥解密 ---- 加密 21 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded()); 22 KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 23 PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); 24 Cipher cipher = Cipher.getInstance("RSA"); 25 cipher.init(Cipher.ENCRYPT_MODE, privateKey); 26 byte[] result = cipher.doFinal(src.getBytes()); 27 System.out.println("私钥加密、公钥解密 ---- 加密:" + encodeBase64Str(result)); 28 29 // 3.私钥加密、公钥解密 ---- 解密 30 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded()); 31 keyFactory = KeyFactory.getInstance("RSA"); 32 PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec); 33 cipher = Cipher.getInstance("RSA"); 34 cipher.init(Cipher.DECRYPT_MODE, publicKey); 35 result = cipher.doFinal(result); 36 System.out.println("私钥加密、公钥解密 ---- 解密:" + new String(result)); 37 38 39 // 4.公钥加密、私钥解密 ---- 加密 40 X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(rsaPublicKey.getEncoded()); 41 KeyFactory keyFactory2 = KeyFactory.getInstance("RSA"); 42 PublicKey publicKey2 = keyFactory2.generatePublic(x509EncodedKeySpec2); 43 Cipher cipher2 = Cipher.getInstance("RSA"); 44 cipher2.init(Cipher.ENCRYPT_MODE, publicKey2); 45 byte[] result2 = cipher2.doFinal(src.getBytes()); 46 System.out.println("公钥加密、私钥解密 ---- 加密:" + encodeBase64Str(result2)); 47 48 // 5.私钥解密、公钥加密 ---- 解密 49 PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded()); 50 KeyFactory keyFactory5 = KeyFactory.getInstance("RSA"); 51 PrivateKey privateKey5 = keyFactory5.generatePrivate(pkcs8EncodedKeySpec5); 52 Cipher cipher5 = Cipher.getInstance("RSA"); 53 cipher5.init(Cipher.DECRYPT_MODE, privateKey5); 54 byte[] result5 = cipher5.doFinal(result2); 55 System.out.println("公钥加密、私钥解密 ---- 解密:" + new String(result5)); 56 57 /** 58 * 对于:“Illegal key size or default parameters”异常,是因为美国的出口限制, 59 * Sun通过权限文件(local_policy.jar、US_export_policy.jar)做了相应限制。因此存在一些问题. 60 * 需要下载Java6或Java7的无政策限制文件local_policy.jar和US_export_policy.jar两个文件,放在jre/lib/security 目录下。 61 */ 62 }
Base64的encode和decode的通用方法
1 public static String encodeBase64Str(byte[] str) { 2 try { 3 String result = new String(Base64.getEncoder().encode(str), "UTF-8"); 4 return result; 5 } catch (UnsupportedEncodingException e) { 6 e.printStackTrace(); 7 } 8 return null; 9 } 10 11 public static byte[] decodeBase64(String str) { 12 try { 13 byte[] result = Base64.getDecoder().decode(str.getBytes("UTF-8")); 14 return result; 15 } catch (UnsupportedEncodingException e) { 16 e.printStackTrace(); 17 } 18 return null; 19 }