Java加密

基本的bai单向加密算法: 

  1. BASE64 严格地说,属于编码格du式,而非加密算法
  2. MD5(Message Digest algorithm 5,信息摘要算法)
  3. SHA(Secure Hash Algorithm,安全散列zhi算法)
  4. HMAC(Hash Message Authentication Code,散列消息鉴别码)

复杂的对称加密(DES、PBE)、非对称加密算法: 

  1. DES(Data Encryption Standard,数据加密算法)
  2. PBE(Password-based encryption,基于密码验证)
  3. RSA(算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman)
  4. DH(Diffie-Hellman算法,dao密钥一致协议)
  5. DSA(Digital Signature Algorithm,数字签名)
  6. ECC(Elliptic Curves Cryptography,椭圆曲线密码编码学)
  7. AES加密

加密大全

私钥,公钥,会话密钥,数字签名

1.BASE64加密

maven依赖:

	
	
	    commons-codec
	    commons-codec
	    1.14
	

 Java代码:

import java.io.UnsupportedEncodingException;

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

public class BASE64Test {
	public static void main(String[] args) {
		String str = "Hello World";  
        try{  
            byte[] encodeBase64 = Base64.encodeBase64(str.getBytes("UTF-8"));  
            System.out.println("Result: " + new String(encodeBase64));  
        } catch(UnsupportedEncodingException e){  
            e.printStackTrace();  
        } 
	}
}

打印结果:

Result: SGVsbG8gV29ybGQ= 

 

2. MD5

  1. 方式1:使用JDK自带MessageDigest
  2. 方式2:使用spring自带工具包DigestUtils

maven依赖:

	
	
	    org.springframework
	    spring-context
	    5.2.7.RELEASE
	

 Java代码:

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.springframework.util.DigestUtils;


public class MD5Test {
	public static void main(String[] args) {
		String str1 = getMD5Str("tianming");
		String str2 = getMD5str2("tianming");
		System.out.println(str1);
		System.out.println(str2);
	}
	
	/**
	 * @Description MD5加密方式1:使用JDK自带MessageDigest
	 * @author yiguang
	 * @date 2020-08-11
	 */
	public static String getMD5Str(String str) {
		byte[] digest = null;
		try {
		    MessageDigest md5 = MessageDigest.getInstance("md5");
		    digest  = md5.digest(str.getBytes("utf-8"));
		} catch (NoSuchAlgorithmException e) {
		    e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
		    e.printStackTrace();
		}
		//16是表示转换为16进制数
		String md5Str = new BigInteger(1, digest).toString(16);
		return md5Str;
        }

	/**
	 * @Description MD5加密方式2:使用spring自带工具包DigestUtils
	 * @author yiguang
	 * @date 2020-08-11
	 */
	public static String getMD5str2(String str) {
		String md5Str = DigestUtils.md5DigestAsHex("原串".getBytes());
		return md5Str;
	}
	
}

打印结果:

 

3. DES加密解密

注意:

  1. des加密之后会乱码,把加密后的字节数组再通过base64加密一次,乱码问题解决,只需要des解密之前用base64解密就可以了。
  2. DES加密和解密过程中,密钥长度都必须是8的倍数

maven依赖:

	
	
	    commons-codec
	    commons-codec
	    1.14
	
	
	
		javax.xml.rpc
		javax.xml.rpc-api
		1.1.1
	

 Java代码:

import java.io.IOException;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;

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

public class DESTest {
	
	public static void main(String[] args) throws IOException {
		String deskey = "password";//des密钥//长度8位
		String content = "真香警告!"; //内容
		System.out.println("DES原始加密内容为:"+content);
		//加密
		byte[] encryptbyte =  desEncrypt(content, deskey); //加密后返回为字节数组
		System.out.println("DES加密后内容为:"+ new String(encryptbyte));
		System.out.println("DES加密后内容为:"+ Base64.encodeBase64String(encryptbyte));
		//解密
		byte[] decryptbyte = desDecrypt(encryptbyte, deskey);  //将加密后返回的字节数组进行解密
		System.out.println("DES解密后内容为:"+ new String(decryptbyte));
   
    }

    /**
     * @Description 加密
     * @author yiguang
     * @date 2020-08-11
     */
    public static byte[] desEncrypt(String context, String key) {
        try {
            // KEY转换
            DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey conventSecretKey = secretKeyFactory.generateSecret(desKeySpec);

            // 加密
            Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, conventSecretKey, new IvParameterSpec(key.getBytes("UTF-8")));
            return cipher.doFinal(context.getBytes("UTF-8"));
        } catch (Throwable e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * @Description 解密
     * @author yiguang
     * @date 2020-08-11
     */
    public static byte[] desDecrypt(byte[] context, String key) {
        try {
            // KEY转换
            DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey conventSecretKey = secretKeyFactory.generateSecret(desKeySpec);

            // 解密
            Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, conventSecretKey, new IvParameterSpec(key.getBytes("UTF-8")));
            return cipher.doFinal(context);
        } catch (Throwable e) {
            e.printStackTrace();
            return null;
        }
    }
}

打印结果:

 Java加密_第1张图片

DES问题:如果将DES加密后的字符串作为url中的参数,那么可能会在获取这些参数的时候,会失败,因为加密后的字符串存在“+ 、=”这种特殊符号。
如:
如果companyId是DES加密后的字符串,那么在后端获取该参数的时候,就无法完整获取到。那么可以如下解决:
第一步:创建UrlUtil类进行url转换

import java.io.UnsupportedEncodingException;

/**  
 * @Title: UrlUtil.java
 * @Package cn.rntd.pc.shop.utils
 * @ClassName: UrlUtil
 * @Description: url加密
 * @author yiguang
 * @date 2020-08-12
 */ 
public class UrlUtil {
    private final static String ENCODE = "GBK"; 

    public static String getURLDecoderString(String str) {
        String result = "";
        if (null == str) {
            return "";
        }
        try {
            result = java.net.URLDecoder.decode(str, ENCODE);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return result;
    }

    public static String getURLEncoderString(String str) {
        String result = "";
        if (null == str) {
            return "";
        }
        try {
            result = java.net.URLEncoder.encode(str, ENCODE);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return result;
    }


    public static void main(String[] args) {
        String str = "测试1";
        System.out.println(getURLEncoderString(str));
        System.out.println(getURLDecoderString(str));
        
    }

}

第二步:先加密,再url转码

import java.io.IOException;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
 
import org.apache.commons.codec.binary.Base64;
 
public class DESEncryption {
	
	public static void main(String[] args) throws IOException {
		String deskey = "password";//des密钥//长度8位
		String content = "真香警告!"; //内容
		System.out.println("DES原始加密内容为:"+content);
		//加密
		byte[] encryptbyte =  desEncrypt(content, deskey); //加密后返回为字节数组
		System.out.println("DES加密后内容为(字节数组):"+ new String(encryptbyte));
		String url0=Base64.encodeBase64String(encryptbyte);
		System.out.println("DES加密后通过base64转换内容为(字符串):"+ url0);
		String url1=UrlUtil.getURLEncoderString(url0);
		System.out.println("前端传参 (经过url转换) :"+url1);
		System.out.println("---------------");
		//解密
		System.out.println("后端接收:"+url1);
		String url3 = UrlUtil.getURLDecoderString(url1);
		System.out.println("经过url解析:"+url3);
		byte[] decoderbyte=Base64.decodeBase64(url3);
		System.out.println("DES加密后通过base64解析内容为(字节数组):"+ decoderbyte);
		byte[] decryptbyte = desDecrypt(encryptbyte, deskey);  //将加密后返回的字节数组进行解密
		System.out.println("DES解密后内容为:"+ new String(decryptbyte));
   
    }
 
    /**
     * @Title: desEncrypt
     * @Description: 加密
     * @param context
     * @param key
     * @return byte[] (这里描述输出参数的作用)
     * @throws
     * @author yiguang
     * @date 2020-08-11
     */ 
    public static byte[] desEncrypt(String context, String key) {
        try {
            // KEY转换
            DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey conventSecretKey = secretKeyFactory.generateSecret(desKeySpec);
 
            // 加密
            Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, conventSecretKey, new IvParameterSpec(key.getBytes("UTF-8")));
            return cipher.doFinal(context.getBytes("UTF-8"));
        } catch (Throwable e) {
            e.printStackTrace();
            return null;
        }
    }
 
    /**
     * @Title: desDecrypt
     * @Description: 解密
     * @param context
     * @param key
     * @return byte[] (这里描述输出参数的作用)
     * @throws
     * @author yiguang
     * @date 2020-08-11
     */ 
    public static byte[] desDecrypt(byte[] context, String key) {
        try {
            // KEY转换
            DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey conventSecretKey = secretKeyFactory.generateSecret(desKeySpec);
 
            // 解密
            Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, conventSecretKey, new IvParameterSpec(key.getBytes("UTF-8")));
            return cipher.doFinal(context);
        } catch (Throwable e) {
            e.printStackTrace();
            return null;
        }
    }
}

打印结果:经过url解析后就可以作为参数传递了

Java加密_第2张图片 

 

4.DSA

DSA(Digital Signature Algorithm)是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSS(DigitalSignature Standard)。
DSA加密算法主要依赖于整数有限域离散对数难题,素数P必须足够大,且p-1至少包含一个大素数因子以抵抗Pohlig &Hellman算法的攻击。M一般都应采用信息的HASH值。DSA加密算法的安全性主要依赖于p和g,若选取不当则签名容易伪造,应保证g对于p-1的大素数因子不可约。其安全性与RSA相比差不多。

DSA 一般用于数字签名和认证。在DSA数字签名和认证中,发送者使用自己的私钥对文件或消息进行签名,接受者收到消息后使用发送者的公钥来验证签名的真实性。DSA只是一种算法,和RSA不同之处在于它不能用作加密和解密,也不能进行密钥交换,只用于签名,它比RSA要快很多.

1. DSA签名及验证

DSA算法中应用了下述参数:

p:L bits长的素数。L是64的倍数,范围是512到1024;

q:p – 1的160bits的素因子;

g:g = h^((p-1)/q) mod p,h满足h < p – 1, h^((p-1)/q) mod p > 1;

x:x < q,x为私钥 ;

y:y = g^x mod p ,( p, q, g, y )为公钥;

H( x ):One-Way Hash函数。DSS中选用SHA( Secure Hash Algorithm )。

p, q, g可由一组用户共享,但在实际应用中,使用公共模数可能会带来一定的威胁。

签名及验证协议:

  • 1.P产生随机数k,k < q;
  • 2.P计算 r = ( g^k mod p ) mod q
    s = ( k^(-1) (H(m) xr)) mod q
    签名结果是( m, r, s )。
  • 3.验证时计算 w = s^(-1)mod q
    u1 = ( H( m ) w ) mod q
    u2 = ( r w ) mod q
    v = (( g^u1 * y^u2 ) mod p ) mod q
    若v = r,则认为签名有效。

举例:B 发消息给A,使用DSA算法进行签名

1.生成素数p=59、素数q=29、h=11、私钥x=7,临时密钥k=10,消息摘要H(M)=26

2.生成g:

g=h^(p-1)/qmod p → g=11^2 mod 59 → g=3

3.计算公钥y

y=g^xmod p → y=3^7 mod 59 →y=2187 mod 59 →y=4

4.进行签名计算

r = (g^k mod p) mod q → r=(59049 mod 59) mod 29 →r=20

s = [k^-1 (H(M) + xr) ] mod q → s=3·(26+140)mod 29 → s=5

5.A收到消息后进行签名验证

w=(s’)^-1mod q → w=6 mod 29 =6

u1=[H(M’)w] mod q → u1=156 mod 29 = 11

u2=(r’)wmod q → u2=120 mod 29=4

v=[(g^u1 · y^u2) mod p] mod q → v= (45349632 mod 59) mod 29 =20

v=r=20

6.验证成功;

2.DSA使用过程

过程:

     构建密钥对:

        发送方:  1.构建密钥对

              2.公布密钥

     发送数据 :

        发送方:  1.使用私钥对数据签名

              2.发送签名,数据

               3.使用公钥,签名验证数据

3. Java实现DSA生成公私钥并加解密

3.1代码如下

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.*;

/**
 * Created by cuiran on 19/1/11.
 * 生成一对文件 publicKey.key 和 privateKey.key ,
 * 公钥要用户发送 ( 文件 , 网络等方法 ) 给其它用户 , 私钥保存在本地
 * 1.生成秘钥对
 * 2.使用私钥进行签名
 * 3.使用公钥校验签名
 * 意义上的加密解密 非内容型的加密解密
 */
public class DSA {

    public static void main(String[] args) {
        //初始化秘钥对写入到文件 生成的是X.509编码格式的 生成的私钥是PKCS#8编码格式
        getKeyPairs();
        //明文签名
        SignatureData("我是cayden,银行账户为622XXXX");
        //校验签名文件
        checkSignature();

    }



    /**
     * 生成秘钥对写入到文件
     * @return
     */
    public static boolean getKeyPairs() {
        try {
            //初始化秘钥管理器
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA");
            keyPairGenerator.initialize(512);
            KeyPair keyPair = keyPairGenerator.genKeyPair();
            //获取秘钥对
            PublicKey publicKey = keyPair.getPublic();
            PrivateKey privateKey = keyPair.getPrivate();

            //直接写入公钥
            ObjectOutputStream out_pub = new ObjectOutputStream(new FileOutputStream("publicKey.key"));
            out_pub.writeObject(publicKey);
            out_pub.close();
            System.out.println("生成的公钥内容为_____:\n "+publicKey);
            //直接写入私钥
            ObjectOutputStream out_pri = new ObjectOutputStream(new FileOutputStream("privateKey.key"));
            out_pri.writeObject(privateKey);
            out_pri.close();
            System.out.println("生成的私钥内容为_____:\n "+privateKey);
            System.out.println("\n生成密钥对成功...");
            return true;
        } catch (java.lang.Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     * 使用私钥进行签名
     * @return
     */
    public static boolean SignatureData(String  info){
        try {
            //1.读取生成的私钥对明文进行签名
            ObjectInputStream in_pri = new ObjectInputStream(new java.io.FileInputStream("privateKey.key"));
            PrivateKey privateKey = (PrivateKey) in_pri.readObject();
            in_pri.close();
            //初始化签名 对明文开始签名
            Signature signature = Signature.getInstance("DSA");
            signature.initSign(privateKey);
            signature.update(info.getBytes());
            // 对信息的数字签名
            byte[] signedbytes = signature.sign();
            System.out.println("签名为_____:"+signedbytes);
            //把签名的密文存到文件中
            ObjectOutputStream out_signature =new ObjectOutputStream(new FileOutputStream("signature.data"));
            //把明文和签名一起写入 也可以分别写入
            out_signature.writeObject(info);
            out_signature.writeObject(signedbytes);
            out_signature.close();
            System.out.println("秘钥签名完成.......");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("私钥签名失败....");
        }
        return false;
    }

    /**
     * 用公钥进行校验
     * @return
     */
    public static boolean checkSignature(){
        try {
            //读取公钥
            ObjectInputStream in_pub=new ObjectInputStream(new FileInputStream("publicKey.key"));
            PublicKey publicKey = (PublicKey) in_pub.readObject();
            //读取签名文件
            ObjectInputStream in_signature=new ObjectInputStream(new FileInputStream("signature.data"));
            //读取签名信息
            String info = (String) in_signature.readObject();
            //用公钥进行校验
            byte[] signedbytes = (byte[]) in_signature.readObject();
            Signature signature = Signature.getInstance("DSA");
            signature.initVerify(publicKey);
            signature.update(info.getBytes());
            //签名信息校验
            if (signature.verify(signedbytes)) {
                System.out.println("签名的内容为____:" + info);
                System.out.println("签名文件校验正常....");
                return true;
            } else{
                System.out.println("签名校验失败");
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }


}

打印结果:

Java加密_第3张图片

你可能感兴趣的:(Java)