Java - 基础 - 密码学

[TOC]

密码学

文章目录
《Java加密与解密的艺术(第2版)》

一、入门

1.1 基本概述

从密码的*上看,大致分为

  • 明文
  • 密文
  • 密钥
  • 加解密算法

在学习密码学之前,了解一下柯克霍夫原则

"即使密码系统的任何细节已为人悉知,只要密匙(key,又称密钥或秘钥)未泄漏,它也应是安全的"

(/*-)

接下来看看几个名词

  1. 公钥

    密码持有者给其他人的一把钥匙,用于数据加密,公钥加密过的数据只能私钥来解

  2. 私钥

    密码持有者独有的一把钥匙,用来解开公钥加密的数据

  3. 摘要

    对需要传输的数据,做一个HASH计算,一般采用SHA1,SHA2来获得

  4. 签名

    数据发送,对需要传输的数据的摘要进行加密,得到的结果就是签名

  5. 签名验证

    数据接收,把拿到的数据,用公钥先对签名解密,然后把解密后的摘要再次用哈希算法校对是否被篡改

(/*-)

从密钥的分类上看

  • 对称加密

    两头用同一把钥匙,优点是加解密速度快,缺点是钥匙不好管理

  • 非对称加密

    两头用不一样的钥匙。优点是钥匙保密性更强,缺点是加解密速度慢

1.2 公钥基础设施

Public Key Infrastructure,PKI

是一个密钥证书管理体系

Java - 基础 - 密码学

就这样,你学废了吗

1.3 常见加密手段

对称加密

不作太多阐述,就是双方拿的锁是一致的,所以加解密速度快,特点如下

  • 加密速度快, 可以加密大文件
  • 密文可逆, 一旦密钥文件泄漏, 就会导致数据暴露
  • 加密后编码表找不到对应字符, 出现乱码
  • 一般结合Base64使用

常见的对称加密算法有:DES(数据加密标准)、AES(高级加密标准/Rijndael加密法)

DES加解密

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;


/**
 * @author 李家民
 */
public class PasswordTest {

    /**
     * 加密
     *
     * @return
     */
    public static String ciphertext()
            throws NoSuchPaddingException,
            NoSuchAlgorithmException,
            InvalidKeyException,
            IllegalBlockSizeException,
            BadPaddingException {
        // 原文
        String dataStr = "好好学习爬上岸";

        // 钥匙 必须是8位
        String key = "77498864";

        // Cipher:密码,获取加密对象
        // transformation:参数表示使用什么类型加密
        Cipher cipher = Cipher.getInstance("DES");

        // 指定秘钥规则
        // 第一个参数表示:密钥,key的字节数组
        // 第二个参数表示:算法
        SecretKeySpec sks = new SecretKeySpec(key.getBytes(), "DES");

        // 对加密进行初始化
        // 第一个参数:表示模式,有加密模式和解密模式
        // 第二个参数:表示秘钥规则
        cipher.init(Cipher.ENCRYPT_MODE, sks);

        // 进行加密(这是数据流加密)
        byte[] bytes = cipher.doFinal(dataStr.getBytes());

        // 打印密文
        // 因为ascii码有负数 解析不出来 所以乱码
        String mData = new String(bytes);
        System.out.println("打印密文(乱码):" + mData);

        Base64.Encoder encoder = Base64.getEncoder();
        String resCipData = encoder.encodeToString(bytes);
        System.out.println("打印密文(正常):" + resCipData);
        return resCipData;
    }


    public static void main(String[] args) throws NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
        // 加密方法 拿密文
        String ciphertext = ciphertext();

        // 获取Cipher对象 填写加密的类型
        Cipher cipher = Cipher.getInstance("DES");

        // 拿密码锁并指定密钥规则
        SecretKeySpec sks = new SecretKeySpec("77498864".getBytes(), "DES");
        cipher.init(Cipher.DECRYPT_MODE, sks);

        // 解密
        // 上面使用的base64编码 下面直接用密文
        byte[] bytesDe = Base64.getDecoder().decode(ciphertext);
        byte[] bytesRes = cipher.doFinal(bytesDe);

        //  因为是明文,所以直接返回
        System.out.println("解密后:" + new String(bytesRes));
    }
}

执行结果

打印密文(乱码):�tCH�k��3����u�B.�~��
打印密文(正常):3wd0Q0jea6TPM6WZnrd13FEIQi69ft/I
解密后:好好学习爬上岸

Base64补等号问题

base64编码为什么要用等号来做最后空白的填补而不是其它

因为这是人为规定的,为的是形成统一标准,在网络传输上不会出现错误。比如说,如果A用了?填充将char转变为base64,而B在转换回来时用的是=将base64转回char,这样子因为标准不统一就会出现错误

省略Java代码....

AES加解密

跟上面那个DES代码一样,只要把加密算法改成AES就行

1.4 区别toString与newString

  • toString()是调用这个object对象的类的toString方法,而new String(str)是根据parameter是一个字节数组,使用java虚拟机默认的编码格式,将这个字节数组decode为对应的字符
  • toString()对象打印的时候使用,new String()一般使用字符转码的时候,byte[]数组的时候

二、Java内置组件包

2.1 领域划分

  • JCA,加密体系结构

    提供加密框架,如证书、数字签名、消息摘要和密钥对产生器

  • JCE,加密扩展

    提供各种加密算法、消息摘要算法和密钥管理等功能

  • JSSE,安全套接字扩展
  • JAAS,鉴别安全服务

然后这些加密的算法或者加密方式等是有一些好人给我们进行了提供,从jdk1.7开始

Java - 基础 - 密码学

2.2 Java.Security

这个是为安全框架提供类和接口,例如说上面那些提供者实现的消息摘要算法,统一的一些规范都是这个包来定义的

Provider

接下来看看Provider类的介绍

Java - 基础 - 密码学

上述类的几个方法

  • String getName()

    返回提供者的名称

  • double getVersion()

    返回提供者的版本号

  • String getInfo

    返回提供者的信息串

Security类最主要的工作就是对提供者进行管理

MessageDigestSpi

提供消息摘要算法的一个接口,通过字节/字节数组的方式进行操作

Java - 基础 - 密码学

下面有这个接口的实现类MessageDigest

Java - 基础 - 密码学

DigestInputStream

也是消息摘要的算法,但是是通过流的方式

DigestInputStream类继承了FilterInputStream类,可以通过读取输入流的方式完成摘要更新,因此我们称之为消息摘要输入流,在指定的读操作方法内部完成MessageDigest类的update()方法

Key接口

所有密钥接口的顶层接口,一切与加密解密有关的操作都离不开Key接口

AlgorithmParameters

引擎类,它提供密码参数的不透明表示,透明与不透明的区别在于

  • 不透明表示:在这种表示中,不可以直接访问各参数域,只能得到与参数集相关联的算法名及该参数集的某类编码
  • 透明表示:用户可以通过相应规范类中定义的某个“get”方法来分别访问每个值

等等....

111111111

2.3 Javax.Crypto

为加密操作提供类和接口,我们所熟知的Cipher就是在这个包下

2.4 spec

java.security.spec包和javax.crypto.spec包

提供了密钥规范算法参数规范的类和接口

2.5 Java.Security.Cert

提供证书解析和管理、证书撤销列表(CRL)和证书路径的类和接口

2.6 Javax.Net.Ssl

用于安全套接字包的类,对构建密钥库、信任库管理及构建基于HTTPS协议的加密安全网络有很大的帮助

2.7 Bouncy Castle

加密组件包

2.8 Commons Codec

编码格式的转换,如Base64、二进制、十六进制、字符集和Url编码的转换

三、进阶篇

3.1 Base64

Base64算法有编码和解码操作可充当加密和解密操作,还有一张字符映射表充当了密钥,算是学习的第一个范例

3.2 不看了以后再补充

1

结束

上一篇:阿里云冬季实战营第四期体验感悟


下一篇:阿里云重磅发布DMS数据库实验室 免费体验数据库引擎