Java 中加密算法的编程使用-学习笔记

Java 中加密算法的编程使用-学习笔记

朱治龙
2022-04-21 / 0 评论 / 17 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2024年02月22日,已超过321天没有更新,若内容或图片失效,请留言反馈。

Base64 编码的编程使用

密码学综述

密码学基本功能

1)机密性
2)鉴别
3)报文完整性
4)不可否认性

基本模型

l28fb4qi.png

密码学算法的分类

  • 消息编码: Base64
  • 消息摘要: MD类、SHA类、MAC
  • 对称密码: DES、3DES、 AES
  • 非对称密码: RSA、DH密钥交换
  • 数字签名: RSASignature、DSASignature

密码学五元组

  • 明文
  • 密文
  • 加密算法(公开)
  • 解密算法(公开)
  • 密钥

密钥

密钥和密码的巨大区别

密钥!=密码
Key != Password
密钥+规则==密码

在密码破解者看来,拿到密钥就等于有了密码!所以,重点在密钥

l28fj6i5.png

对称密码(传统密码)与非对称密码(公钥密码)

  • 对称密码:加解密使用相同密钥的密码体制
  • 非对称密码:加解密使用不同的密钥一公钥与私钥

Java编程中常用类

  1. 消息编码
    BASE64Encoder、BASE64Decoder
  2. 消息摘要
    MessageDigest
  3. 对称密码
    KeyGenerator、SecretKey、 Cipher
  4. 非对称密码
    KeyPairGenerator、KeyFactory、 KeyPair、PublicKey、 PrivateKey、 Cipher
  5. 数字签名
    Signature

Base64 算法的编程使用

  1. Base64编码示例
    密文: UGFyYXRlcmE=

明文: Paratera

  1. Base64算法定义
    Base64是一种基于64个字符的编码算法,以任意8位字节序列组合的描述形式,这种形式不易直接识别。经Base64编码后的字符串的字符数是以4为单位的整数倍。
  2. Base64 密钥
    Base64 密钥

4.Base64 编程使用

引入sun.misc.BASE64Decoder.jar

1、加密:

byte[] data = "Paratera".getBytes();
String result= new BASE64Encoder().encode(data) ;

2、解密:

byte[] result = new BASE64Decoder().decodeBuffer(data) ;

Base64 算法的实际应用

使用Telnet 发送邮件:
使用Telnet 发送邮件

pubLic class Base64Util {
  public static String enc ryptBase64(byte[] data){
    return new BASE64Encoder().encode(data);
  }
  public static String dec ryptBase64(String data) throws IOException{
    byte[] resultBytes = new BASE64Decoder().decodeBuffer(data);
    return new String( resultBytes);
  }
}


pubLic class SMTPMain {
  public static void main(String[] args) {
    //用户名密码
    String sender = "cnsmtp01@163.com"; 
    String receiver = "cnsmtp02@163. com";
    String password = "computer";
    //将用户名和密码进行Base64编码
    String userBase64 = Base64Util.encryptBase64(sender.substring(0, sender.index0f("@")).getBytes());
    String passBase64 = Base64Util.encryptBase64(password.getBytes());
    try {
      Socket socket = new Socket("smtp.163.com", 25);
      InputStream inputStream = socket.getInputStream();
      OutputStream outputStream = socket.getOutputStream();
      BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
      PrintWriter writter = new PrintWriter(outputStream, true);
      System.out.println(reader.readLine());

      // HELO
      writter.println("HELO Paratera");
      System.out.println(reader.readLine());
      // AUTH LOGIN >> >Base64
      writter.println( "AUTH LOGIN");
      System.out.println(reader.readLine());
      writter.println(userBase64);
      System.out.println(reader.readLine());
      writter.println(passBase64);
      System.out.println(reader.readLine());
      // Set "MAIL FROM" and "RCPT TO"
      writter.println("MAIL FROM:<" + sender + ">");
      System.out.println(reader.readLine());
      writter.println( "RCPT TO:<" + receiver + ">");
      System.out.println(reader.readLine());
      // Set "DATA"
      writter.println("DATA");
      System.out.println(reader.readLine());
      writter.println("SUBJECT:你好并行集团");
      writter.println("FROM:" + sender);
      writter.println("T0:" + receiver);
      writter.println("Content-Type: text/plain;charset=\"gb2312\"");
      writter.println();
      writter.println("北京并行科技股份有限公司(简称并行科技,PARATERA,股票代码:839493,挂牌新三板)成立于2007年,是国内领先的超算云服务和运营服务提供商,提供超算公有云服务、超算行业云服务、AI云服务、设计仿真云和计算资源建设及运营服务。");
      writter.println(".");
      writter.println("");
      System.out.println(reader.readLine());
      
      //发送完毕了, 和服务器拜拜
      writter.println("RSET");
      System.out.println(reader.readLine());
      writter.println("QUIT");
      System.out.println(reader.readLine());
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

消息摘要的编程使用

消息摘要概述

唯一对应一个消息或文本的固定长度的值,由一个单向Hash加密函数对消息进行作用而产生

消息摘要的分类:

  • (1) MD (Message Digest) :消息摘要算法
  • (2) SHA (Secure Hash Algorithm) : 安全散列算法
  • (3) MAC (Message Authentication Code) :消息认证码算法

消息摘要的日常应用

验证数据完整性(防止在传输途中被篡改)
验证数据完整性

MD算法的编程使用

为计算机安全领域广泛使用的一种散列函数,用以提供消息的 完整性 保护

MD系列算法(JDK)

算法数据长度摘要长度
MD2任意128
MD5任意128

MD算法编程使用

核心代码

//初始化MessageDigest
MessageDigest md5 = MessageDigest.getInstance("MD5");
//更新, data为原始数据
md5.update(data);
/生成摘要
byte[] result= md5.digest();

完整示例代码:

// ---------1.BytesToHex.java---------
package net.wljy.crypt.util;

/**
 * 字节转16进制
 * 
 * @author paratera
 *
 */
public class BytesToHex {
    public static String fromBytesToHex(byte[] resultBytes) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < resultBytes.length; i++) {
            if (Integer.toHexString(0xFF & resultBytes[i]).length() == 1) {
                builder.append("0").append(Integer.toHexString(0xFF & resultBytes[i]));
            } else {
                builder.append(Integer.toHexString(0xFF & resultBytes[i]));
            }
        }
        return builder.toString();
    }
}

// ---------2.MessageDigestUtil.java---------
package net.wljy.crypt;

import java.io.File;
import java.io.FileInputStream;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import net.wljy.crypt.util.BytesToHex;

public class MessageDigestUtil {
    /**
     * MD5字符串加密
     * @param data    待加密字符串
     * @return
     */
    public static String encryptMD5(byte [] data) {
        MessageDigest md5;
        try {
            md5 = MessageDigest.getInstance("MD5");
            md5.update(data);
            byte[] resultBytes = md5.digest();
            return BytesToHex.fromBytesToHex(resultBytes);
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
        
    }
    /**
     * 获取文件MD5值
     * @param filePath    文件路径
     * @return
     */
    public static String getMD5ofFile(String filePath) {
        FileInputStream fis;
        try {
            fis = new FileInputStream(new File(filePath));
            DigestInputStream dis = new DigestInputStream(fis, MessageDigest.getInstance("MD5"));
            byte[] buffer = new byte[1024];
            int read = dis.read(buffer, 0, 1024);
            while(read != -1) {
                read = dis.read(buffer, 0, 1024);
            }
            MessageDigest md = dis.getMessageDigest();
            return BytesToHex.fromBytesToHex(md.digest());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
        
    }
}
// ---------3.MD5Test.java---------
package net.wljy.crypt;

public class MD5Test {
    public static final String DATA = "并行集团";
    public static void main(String[] args) {
        String md5Str = MessageDigestUtil.encryptMD5(DATA.getBytes());
        System.out.println(md5Str);
        String fileMd5Str = MessageDigestUtil.getMD5ofFile("D:/API接口文档.html");
        System.out.println("文件MD5:" + fileMd5Str);
    }
}

SHA算法的编程使用

安全哈希算法,主要适用于数字签名标准里面定义的数字签名算法

SHA算法种类

算法数据长度摘要长度
SHA-1任意160
SHA-256任意256
SHA-384任意384
SHA-512任意512

核心代码

//初始化MessageDigest
MessageDigest sha = MessageDigest.getInstance("SHA-x"); // SHA-x需替换为具体的算法名称
//更新, data为原始数据
sha.update(data);
/生成摘要
byte[] result= sha.digest();

示例代码:

    /**
     * 计算某一数据的hash摘要值
     * @param data
     * @return
     */
    public static String encryptSHA(byte [] data) {
        try {
            MessageDigest sha = MessageDigest.getInstance("SHA-256");
            sha.update(data);
            return BytesToHex.fromBytesToHex(sha.digest());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

HMAC算法的编程使用

引言:

单一MD或SHA算法缺点?
摘要值容易被篡改!
l29v5x64.png

结合了MD5和SHA算法的优势,同时用 密钥 对摘要加密,是一种更为安全的消息摘要算法。

l29v8nh0.png

HMAC算法的种类

算法数据长度摘要长度
HmacMD5任意128
HmacSHA1任意160
HmacSHA256任意256
HmacSHA384任意384
HmacSHA512任意512

如何生成密钥

KeyGenerator!

核心代码

1.构建密钥

//初始化KeyGenerator
KeyGenerator keyGen = KeyGenerator.getInstance("HmacMD5");
//产生密钥
SecretKey secretKey = keyGen.generateKey();
//得到密钥字节数组
byte[] key= secretKey.getEncoded();

2.执行消息摘要

//从字节数组还原密钥
SecretKey secretKey = new SecretKeySpec(key, "HmacMD5");
//实例化Mac
Mac mac = Mac.getInstance("HmacMD5");
//用密钥初始化Mac
mac.init(secretKey);
//执行消息摘要
byte[] result = mac.doFinal(data);

散列函数特征:

  • (1)输入任意长度数据,输出固定长度散列值,计算很容易,过程不可逆
  • (2)对于某数据,其散列值固定
  • (3)两个数据不同,则对应的散列值也不同
  • (4)两个散列值不同,则对应的原始输入数据也不同

2.散列函数破解

(1)真破解:2005年2月,王小云教授破解了SHA-1 算法,已知数据A和其散列值,找到了另一个数据B与A的散列值相同
散列函数破解-真破解

(2)假破解:根据数据库查询散列值,找到其对应的数据明文,根本在于数据库的查询!
散列函数破解-假破解

对称密码的编程使用

对称密码概述

1、加密密钥和解密密钥相同,对于大多数对称密码算法,加解密过程互逆
2、加解密通信模型
l2a1jitx.png

3、特点:算法公开、计算量小、加密速度快、加密效率高
4、弱点:双方都使用同样密钥,安全性得不到保证
5、分组密码工作模式

  • (1) ECB: 电子密码本
  • (2) CBC: 密文链接
  • (3) CFB: 密文反馈
  • (4) OFB:输出反馈
  • (5) CTR: 计数器
    6、分组密码填充方式
  • (1) NoPadding
  • (2) PKCS5Padding
  • (3) ISO10126Padding

7、常用对称密码:

  • (1) DES (Data Encryption Standard)
  • (2) 3DES (Triple DES、DESede)3重DES
  • (3) AES (Advanced Encryption Standard)

DES算法的编程使用

  1. DES:数据加密标准,是对称加密算法领域中的典型算法
  2. 特点:密钥偏短(56位)、 生 命周期短
  3. JDK实现
    | 算法 | 密钥长度 | 默认密钥长度 | 工作模式 | 填充方式 |
DES5656ECB、CBC、PCBC、CTR、CTS、CFB、CFB8-CFB128、OFB、OFB8-OFB128NoPadding、PKCS5Padding、ISO10126Padding

4、示例代码

// ---------1.DESUtil.java---------
package net.wljy.crypt.des;

import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class DESUtil {
    /**
     * 生成密钥
     * 
     * @return
     */
    public static byte[] initKey() {
        try {
            KeyGenerator keyGen = KeyGenerator.getInstance("DES");
            keyGen.init(56);
            SecretKey secretKey = keyGen.generateKey();
            return secretKey.getEncoded();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * DES加密
     * 
     * @param data 要加密的数据
     * @param key  密钥
     * @return
     */
    public static byte[] encrypt(byte[] data, byte[] key) {
        SecretKey secretKey = new SecretKeySpec(key, "DES");
        try {
            // DES/ECB/NoPadding --> 加密方式/工作模式/填充方式,没有严格要求的场景只写加密方式即可
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            return cipher.doFinal(data);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * DES加密
     * 
     * @param data 要解密的数据
     * @param key  密钥
     * @return
     */
    public static byte[] decrypt(byte[] encryptedData, byte[] key) {
        SecretKey secretKey = new SecretKeySpec(key, "DES");
        try {
            // DES/ECB/NoPadding --> 加密方式/工作模式/填充方式,没有严格要求的场景只写加密方式即可
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            return cipher.doFinal(encryptedData);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}

// ---------2.DESTest.java---------
package net.wljy.crypt.des;

import net.wljy.crypt.util.BytesToHex;

public class DESTest {
    public static final String DATA = "并行集团";

    public static void main(String[] args) {
        // 获取密钥
        byte[] initKey = DESUtil.initKey();
        System.out.println("secretKey:" + BytesToHex.fromBytesToHex(initKey));
        // 加密数据
        byte[] desResultData = DESUtil.encrypt(DATA.getBytes(), initKey);
        System.out.println("desResultData:" + BytesToHex.fromBytesToHex(desResultData));
        // 解密数据
        byte[] decryptResultData = DESUtil.decrypt(desResultData, initKey);
        System.out.println("decryptResultData:" + new String(decryptResultData));
    }
}

3DES算法的编程使用

1、3DES:将密钥长度增至112位或168位,通过增加迭代次数提高安全性
2、缺点:处理速度较慢、密钥计算时间较长、加密效率不高
3、JDK实现

算法密钥长度默认密钥长度工作模式填充方式
3DES112、168168ECB、CBC、PCBC、CTR、CTS、CFB、CFB8-CFB128、OFB、OFB8-OFB128NoPadding、PKCS5Padding、ISO10126Padding

核心代码

1、生成密钥

KeyGenerator keyGen = KeyGenerator.getInstance("DESede");
keyGen.init(168); //可指定密钥长度为112或168, 默认为168
SecretKey secretKey = keyGen.generateKey();

2.加/解密

SecretKey secretKey = new SecretKeySpec(key, "DESede");
Cipher cipher = Cipher.getInstance("DESede");
cipher.init(Cipher.ENCRYPT_MODE,secretKey);
byte[] cipherByte = cipher.doFinal(data);

4、完整示例代码

// ---------1.TripleDESUtil.java---------
package net.wljy.crypt.tripledes;

import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

/**
 * 3DES
 * 
 * @author paratera
 *
 */
public class TripleDESUtil {
    /**
     * 生成密钥
     * 
     * @return
     */
    public static byte[] initKey() {
        KeyGenerator keyGen;
        try {
            keyGen = KeyGenerator.getInstance("DESede");
            keyGen.init(168); // 112 168
            SecretKey secretKey = keyGen.generateKey();
            return secretKey.getEncoded();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 3DES加密
     * 
     * @param data 待加密数据
     * @param key  密钥
     * @return
     */
    public static byte[] encrypt(byte[] data, byte[] key) {
        try {
            SecretKey secretKey = new SecretKeySpec(key, "DESede");
            Cipher cipher = Cipher.getInstance("DESede");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            return cipher.doFinal(data);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 3DES解密
     * 
     * @param encrypedData 待解加密数据
     * @param key          密钥
     * @return
     */
    public static byte[] decrypt(byte[] encrypedData, byte[] key) {
        try {
            SecretKey secretKey = new SecretKeySpec(key, "DESede");
            Cipher cipher = Cipher.getInstance("DESede");
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            return cipher.doFinal(encrypedData);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}


// ---------2.TripleDESTest.java---------
package net.wljy.crypt.tripledes;

import net.wljy.crypt.util.BytesToHex;

public class TripleDESTest {
    public static final String DATA = "并行集团";

    public static void main(String[] args) {
        // 获取密钥
        byte[] initKey = TripleDESUtil.initKey();
        System.out.println("secretKey:" + BytesToHex.fromBytesToHex(initKey));
        // 加密数据
        byte[] resultData = TripleDESUtil.encrypt(DATA.getBytes(), initKey);
        System.out.println("3DESResultData:" + BytesToHex.fromBytesToHex(resultData));
        // 解密数据
        byte[] decryptResultData = TripleDESUtil.decrypt(resultData, initKey);
        System.out.println("3DESdecryptResultData:" + new String(decryptResultData));
    }

}

AES算法的编程使用

1、AES:高级数据加密标准,能够有效抵御已知的针对DES算法的所有攻击
2、特点:密钥建立时间短、灵敏性好、内存需求低、安全性高
3、JDK实现

算法密钥长度默认密钥长度工作模式填充方式
AES128、192、256128ECB、CBC、PCBC、CTR、CTS、CFB、CFB8-CFB128、OFB、OFB8-OFB128NoPadding、PKCS5Padding、ISO10126Padding

核心代码

1、生成密钥

KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128); //默认128,获得无政策权限后可为192或256
SecretKey secretKey = keyGen.generateKey();

2、加/解密

SecretKey secretKey = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE,secretKey); // ENCRYPT_MODE:加密 || DECRYPT_MODE:解密
byte[] cipherByte = cipher.doFinal(data);

政策权限文件

keyGen.init(),如果给值为19或256会报错,JDK8及之前的文件可到如下地址下载政策文件:https://www.oracle.com/java/technologies/javase-jce-all-downloads.html。下载后覆盖jdk/jre/lib/security下的两个jar包即可。

非对称密码的编程使用

非对称密码概述

1、对称密码中的密钥配送存在不安全问题
对称密码中的密钥配送存在不安全问题
2、非对称密码通信模型
非对称密码通信模型

l2a619zo.png

3、非对称密码的特征

  • (1).需要两个密钥来进行加密和解密,分别为公钥和私钥
  • (2).公钥和私钥相互配对,称为KeyPair

4、非对称密码的优缺点

  • (1).优点:相比于对称密码,安全性更高
  • (2).缺点:加解密花费时间长、速度慢

5、常用非对称密码:

  • (1).DH密钥交换算法
  • (2).RSA算法
  • (3).EIGamal算法

6、非对称密码的作用

  • (1).密钥交换(DH)
  • (2).加密/解密(RSA)
  • (3).数字签名(RSA)

DH 算法的编程使用

RSA 算法的编程使用

数字签名的编程使用0

数字签名概述

RSASignature 算法的编程使用

DSASignature 算法的编程使用

0

评论 (0)

取消