1 sha加密:
安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准(Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA)。对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。该算法经过加密专家多年来的发展和改进已日益完善,并被广泛使用。该算法的思想是接收一段明文,然后以一种不可逆的方式将它转换成一段(通常更小)密文,也可以简单的理解为取一串输入码(称为预映射或信息),并把它们转化为长度较短、位数固定的输出序列即散列值(也称为信息摘要或信息认证代码)的过程。散列函数值可以说是对明文的一种“指纹”或是“摘要”所以对散列值的数字签名就可以视为对此明文的数字签名。
Java 已经实现了 SHA-256 和 SHA-512 两种 Hash 算法
利用 java.security.MessageDigest 调用已经集成的 Hash 算法
创建 Encrypt 对象,并调用 SHA256 或者 SHA512 并传入要加密的文本信息,分别得到 SHA-256 或 SHA-512 两种被加密的 hash 串。
若要改为 MD5 算法,修改传入参数 strType 为 "MD5" 即可得到 MD5 加密功能。
- /**
- * @file Encrypt.java
- * @date 2016年8月5日
- * @version 3.4.1
- *
- * Copyright (c) 2013 Sihua Tech, Inc. All Rights Reserved.
- */
- package encrypt;
- /**
- *
- *
- * @author chengjian.he
- * @version 3.4, 2016年8月5日 上午10:05:37
- * @since
- */
- import java.security.MessageDigest;
- import java.security.NoSuchAlgorithmException;
- public class Encrypt
- {
- /**
- * 传入文本内容,返回 SHA-256 串
- *
- * @param strText
- * @return
- */
- public String SHA256(final String strText)
- {
- return SHA(strText, "SHA-256");
- }
- /**
- * 传入文本内容,返回 SHA-512 串
- *
- * @param strText
- * @return
- */
- public String SHA512(final String strText)
- {
- return SHA(strText, "SHA-512");
- }
- /**
- * 字符串 SHA 加密
- *
- * @param strSourceText
- * @return
- */
- private String SHA(final String strText, final String strType)
- {
- // 返回值
- String strResult = null;
- // 是否是有效字符串
- if (strText != null && strText.length() > 0)
- {
- try
- {
- // SHA 加密开始
- // 创建加密对象 并傳入加密類型
- MessageDigest messageDigest = MessageDigest.getInstance(strType);
- // 传入要加密的字符串
- messageDigest.update(strText.getBytes());
- // 得到 byte 類型结果
- byte byteBuffer[] = messageDigest.digest();
- // 將 byte 轉換爲 string
- StringBuffer strHexString = new StringBuffer();
- // 遍歷 byte buffer
- for (int i = 0; i < byteBuffer.length; i++)
- {
- String hex = Integer.toHexString(0xff & byteBuffer[i]);
- if (hex.length() == 1)
- {
- strHexString.append('0');
- }
- strHexString.append(hex);
- }
- // 得到返回結果
- strResult = strHexString.toString();
- }
- catch (NoSuchAlgorithmException e)
- {
- e.printStackTrace();
- }
- }
- return strResult;
- }
- public static void main(String args[]){
- Encrypt ey = new Encrypt();
- System.out.println(ey.SHA("ILoveYou", "MD5"));//62accaf23ac9a73c0b28765b7dfaf75a
- }
- }
2 Base64
Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。Base64编码可用于在HTTP环境下传递较长的标识信息。例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码具有不可读性,即所编码的数据不会被人用肉眼所直接看到。
- /**
- * @file Base64.java
- * @date 2016年8月5日
- * @version 3.4.1
- *
- * Copyright (c) 2013 Sihua Tech, Inc. All Rights Reserved.
- */
- package encrypt;
- import java.io.UnsupportedEncodingException;
- import Decoder.BASE64Decoder;
- import Decoder.BASE64Encoder;
- /**
- *
- *
- * @author chengjian.he
- * @version 3.4, 2016年8月5日 上午10:32:23
- * @since Yeexun 3.4
- */
- public class Base64 {
- // 加密
- public String getBase64(String str) {
- byte[] b = null;
- String s = null;
- try {
- b = str.getBytes("utf-8");
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- if (b != null) {
- s = new BASE64Encoder().encode(b);
- }
- return s;
- }
- // 解密
- public String getFromBase64(String s) {
- byte[] b = null;
- String result = null;
- if (s != null) {
- BASE64Decoder decoder = new BASE64Decoder();
- try {
- b = decoder.decodeBuffer(s);
- result = new String(b, "utf-8");
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- return result;
- }
- public static void main(String args[]){
- Base64 b6 = new Base64();
- System.out.println(b6.getBase64("ILoveYou"));
- System.out.println(b6.getFromBase64(b6.getBase64("ILoveYou")));
- }
- }
- SUxvdmVZb3U=
- ILoveYou
3 Base64Encoder
一直以来Base64的加密解密都是使用sun.misc包下的BASE64Encoder及BASE64Decoder的sun.misc.BASE64Encoder/BASE64Decoder类。这人个类是sun公司的内部方法,并没有在java api中公开过,不属于JDK标准库范畴,但在JDK中包含了该类,可以直接使用。
- /**
- * @file Base64Encoder.java
- * @date 2016年8月5日
- * @version 3.4.1
- *
- * Copyright (c) 2013 Sihua Tech, Inc. All Rights Reserved.
- */
- package encrypt;
- /**
- *
- *
- * @author chengjian.he
- * @version 3.4, 2016年8月5日 上午10:44:22
- * @since Yeexun 3.4
- */
- public class Base64Encoder {
- public static String getBASE64(String s) {
- if (s == null)
- return null;
- return (new sun.misc.BASE64Encoder()).encode(s.getBytes());
- }
- // 将 BASE64 编码的字符串 s 进行解码 解密
- public static String getFromBASE64(String s) {
- if (s == null)
- return null;
- sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
- try {
- byte[] b = decoder.decodeBuffer(s);
- return new String(b);
- } catch (Exception e) {
- return null;
- }
- }
- public static String mTOa(Object ming){
- return Base64Encoder.getBASE64(Base64Encoder.getBASE64(Base64Encoder.getBASE64((String)ming)));
- }
- public static String aTOm(String an){
- return Base64Encoder.getFromBASE64(Base64Encoder.getFromBASE64(Base64Encoder.getFromBASE64(an)));
- }
- public static void main(String[] args) {
- String a = mTOa("100000.89".toString());
- System.out.println(a);//加密
- System.out.println(aTOm(a));//解密
- }
- }
4 RSA
缺点
编辑- /**
- * @file RSATool.java
- * @date 2016年8月5日
- * @version 3.4.1
- *
- * Copyright (c) 2013 Sihua Tech, Inc. All Rights Reserved.
- */
- package encrypt;
- /**
- *
- *
- * @author chengjian.he
- * @version 3.4, 2016年8月5日 上午10:51:35
- * @since Yeexun 3.4
- */
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.ObjectInputStream;
- import java.io.ObjectOutputStream;
- import java.security.Key;
- import java.security.KeyPair;
- import java.security.KeyPairGenerator;
- import java.security.NoSuchAlgorithmException;
- import java.security.interfaces.RSAPrivateKey;
- import java.security.interfaces.RSAPublicKey;
- import javax.crypto.Cipher;
- import javax.crypto.NoSuchPaddingException;
- public class RSATool {
- public static void makekeyfile(String pubkeyfile, String privatekeyfile)
- throws NoSuchAlgorithmException, FileNotFoundException, IOException {
- // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
- KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
- // 初始化密钥对生成器,密钥大小为1024位
- keyPairGen.initialize(1024);
- // 生成一个密钥对,保存在keyPair中
- KeyPair keyPair = keyPairGen.generateKeyPair();
- // 得到私钥
- RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
- // 得到公钥
- RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
- // 生成私钥
- ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
- privatekeyfile));
- oos.writeObject(privateKey);
- oos.flush();
- oos.close();
- oos = new ObjectOutputStream(new FileOutputStream(pubkeyfile));
- oos.writeObject(publicKey);
- oos.flush();
- oos.close();
- System.out.println("make file ok!");
- }
- /**
- *
- * @param k
- * @param data
- * @param encrypt
- * 1 加密 0解密
- * @return
- * @throws NoSuchPaddingException
- * @throws Exception
- */
- public static byte[] handleData(Key k, byte[] data, int encrypt)
- throws Exception {
- if (k != null) {
- Cipher cipher = Cipher.getInstance("RSA");
- if (encrypt == 1) {
- cipher.init(Cipher.ENCRYPT_MODE, k);
- byte[] resultBytes = cipher.doFinal(data);
- return resultBytes;
- } else if (encrypt == 0) {
- cipher.init(Cipher.DECRYPT_MODE, k);
- byte[] resultBytes = cipher.doFinal(data);
- return resultBytes;
- } else {
- System.out.println("参数必须为: 1 加密 0解密");
- }
- }
- return null;
- }
- public static void main(String[] args) throws Exception {
- String pubfile = "d:/temp/pub.key";
- String prifile = "d:/temp/pri.key";
- makekeyfile(pubfile, prifile);
- ObjectInputStream ois = new ObjectInputStream(new FileInputStream(pubfile));
- RSAPublicKey pubkey = (RSAPublicKey) ois.readObject();
- ois.close();
- ois = new ObjectInputStream(new FileInputStream(prifile));
- RSAPrivateKey prikey = (RSAPrivateKey) ois.readObject();
- ois.close();
- // 使用公钥加密
- String msg = "~O(∩_∩)O哈哈~";
- String enc = "UTF-8";
- // 使用公钥加密私钥解密
- System.out.println("原文: " + msg);
- byte[] result = handleData(pubkey, msg.getBytes(enc), 1);
- System.out.println("加密: " + new String(result, enc));
- byte[] deresult = handleData(prikey, result, 0);
- System.out.println("解密: " + new String(deresult, enc));
- msg = "嚯嚯";
- // 使用私钥加密公钥解密
- System.out.println("原文: " + msg);
- byte[] result2 = handleData(prikey, msg.getBytes(enc), 1);
- System.out.println("加密: " + new String(result2, enc));
- byte[] deresult2 = handleData(pubkey, result2, 0);
- System.out.println("解密: " + new String(deresult2, enc));
- }
- }
- make file ok!
- 原文: ~O(∩_∩)O哈哈~
- 加密: �A N�ډB�����ym��r�C��ʇ�������U
5 AES对称加密
加密技术可以分为对称与非对称两种.
对称加密,解密,即加密与解密用的是同一把秘钥,常用的对称加密技术有DES,AES等
而非对称技术,加密与解密用的是不同的秘钥,常用的非对称加密技术有RSA等
为什么要有非对称加密,解密技术呢
假设这样一种场景A要发送一段消息给B,但是又不想以明文发送,所以就需要对消息进行加密.如果采用对称加密技术,那么加密与解密用的是同一把秘钥.除非B事先就知道A的秘钥,并且保存好.这样才可以解密A发来的消息.
由于对称技术只有一把秘钥,所以秘钥的管理是一个很麻烦的问题.而非对称技术的诞生就解决了这个问题.非对称加密与解密使用的是不同的秘钥,并且秘钥对是一一对应的,即用A的私钥加密的密文只有用A的公钥才能解密.
这样的话,每个人都有两把秘钥,私钥和公钥,私钥是只有自己才知道的,不能告诉别人,而公钥是公开的,大家都可以知道.这样,当A想要发送消息给B的时候,只需要用B的公钥对消息进行加密就可以了,由于B的私钥只有B才拥有,所以A用B的公钥加密的消息只有B才能解开.而B想更换自己的秘要时也很方便,只须把公钥告诉大家就可以了.
那么,既然非对称加密如此之好,对称加密就没有存在的必要了啊,其实不然,由于非对称加密算法的开销很大,所以如果直接以非对称技术来加密发送的消息效率会很差.那么怎么办呢?解决的办法也很简单,就是把对称加密技术与非对称加密技术结合起来使用.
还是这个例子:A要发送一个消息给B.
一,A先生成一个对称秘钥,这个秘钥可以是随机生成的,
二,A用B的公钥加密第一步生成的这个对称秘钥
三,A把加密过的对称秘钥发给B
四,A用第一步生成的这个对称秘钥加密实际要发的消息
五,A把用对称秘钥加密的消息发给B
对于B
他先收到A发来的对称秘钥,这个秘钥是用B的公钥加密过的,所以B需要用自己的私钥来解密这个秘钥
然后B又收到A发来的密文,这时候用刚才解密出来的秘钥来解密密文
这样子的整个过程既保证了安全,又保证了效率.
接下来是Java实现:
我这个Java实现使用的是AES的对称加密和RSA的非对称加密(DES的对称加密实现方法和AES的是一样的,但是由于DES算法本身有缺陷,容易被破解,所以现在多用其升级版AES对称加密)
- /**
- * @file AES.java
- * @date 2016年8月5日
- * @version 3.4.1
- *
- * Copyright (c) 2013 Sihua Tech, Inc. All Rights Reserved.
- */
- package encrypt;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- /**
- *
- *
- * @author chengjian.he
- * @version 3.4, 2016年8月5日 上午11:35:13
- * @since Yeexun 3.4
- */
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.ObjectInputStream;
- import java.io.OutputStream;
- import java.security.InvalidKeyException;
- import java.security.Key;
- import java.security.NoSuchAlgorithmException;
- import java.security.SecureRandom;
- import java.security.interfaces.RSAPrivateKey;
- import java.security.interfaces.RSAPublicKey;
- import javax.crypto.BadPaddingException;
- import javax.crypto.Cipher;
- import javax.crypto.IllegalBlockSizeException;
- import javax.crypto.KeyGenerator;
- import javax.crypto.NoSuchPaddingException;
- import javax.crypto.ShortBufferException;
- public class AES {
- private Key key;
- /**
- * 生成AES对称秘钥
- * @throws NoSuchAlgorithmException
- */
- public void generateKey() throws NoSuchAlgorithmException {
- KeyGenerator keygen = KeyGenerator.getInstance("AES");
- SecureRandom random = new SecureRandom();
- keygen.init(random);
- this.key = keygen.generateKey();
- }
- /**
- * 加密
- * @param in
- * @param out
- * @throws InvalidKeyException
- * @throws ShortBufferException
- * @throws IllegalBlockSizeException
- * @throws BadPaddingException
- * @throws NoSuchAlgorithmException
- * @throws NoSuchPaddingException
- * @throws IOException
- */
- public void encrypt(InputStream in, OutputStream out) throws InvalidKeyException, ShortBufferException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, IOException {
- this.crypt(in, out, Cipher.ENCRYPT_MODE);
- }
- /**
- * 解密
- * @param in
- * @param out
- * @throws InvalidKeyException
- * @throws ShortBufferException
- * @throws IllegalBlockSizeException
- * @throws BadPaddingException
- * @throws NoSuchAlgorithmException
- * @throws NoSuchPaddingException
- * @throws IOException
- */
- public void decrypt(InputStream in, OutputStream out) throws InvalidKeyException, ShortBufferException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, IOException {
- this.crypt(in, out, Cipher.DECRYPT_MODE);
- }
- /**
- * 实际的加密解密过程
- * @param in
- * @param out
- * @param mode
- * @throws IOException
- * @throws ShortBufferException
- * @throws IllegalBlockSizeException
- * @throws BadPaddingException
- * @throws NoSuchAlgorithmException
- * @throws NoSuchPaddingException
- * @throws InvalidKeyException
- */
- public void crypt(InputStream in, OutputStream out, int mode) throws IOException, ShortBufferException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
- Cipher cipher = Cipher.getInstance("AES");
- cipher.init(mode, this.key);
- int blockSize = cipher.getBlockSize();
- int outputSize = cipher.getOutputSize(blockSize);
- byte[] inBytes = new byte[blockSize];
- byte[] outBytes = new byte[outputSize];
- int inLength = 0;
- boolean more = true;
- while (more) {
- inLength = in.read(inBytes);
- if (inLength == blockSize) {
- int outLength = cipher.update(inBytes, 0, blockSize, outBytes);
- out.write(outBytes, 0, outLength);
- } else {
- more = false;
- }
- }
- if (inLength > 0)
- outBytes = cipher.doFinal(inBytes, 0, inLength);
- else
- outBytes = cipher.doFinal();
- out.write(outBytes);
- out.flush();
- }
- public void setKey(Key key) {
- this.key = key;
- }
- public Key getKey() {
- return key;
- }
- public static void main(String[] args) throws Exception {
- AES aes = new AES();
- aes.generateKey();
- File file = new File("D:/aa.jpg");
- FileInputStream in = new FileInputStream(file);
- File file1 = new File("D:/temp/pub.key");
- FileOutputStream out = new FileOutputStream(file1);
- aes.encrypt(in, out);
- aes.decrypt(in, out);
- }
- }