密码学看这篇就够了_密码学单表代替、多表代替例子-程序员宅基地

技术标签: 安全  数字签名  非对称加密  数字证书  密码学  对称加密  

概念及发展

概念

密码学是网络安全、信息安全、区块链等产品的基础,常见的非对称加密、对称加密、散列函数等,都属于密码学范畴。
密码学有数千年的历史,从最开始的替换法到如今的非对称加密算法,经历了古典密码学,近代密码学和现代密码学三个阶段。密码学不仅仅是数学家们的智慧,更是如今网络空间安全的重要基础。

古典密码学(1949年之前)

数据的安全基于算法的保密
替换法
用固定的信息将原文替换成无法直接阅读的密文信息。例如将 b 替换成 w ,e 替换成p ,这样bee 单词就变换成了wpp,不知道替换规则的人就无法阅读出原文的含义。
1)单表替换
单表替换即只有一张原文密文对照表单,发送者和接收者用这张表单来加密解密。在上述例子中,表单即为:a b c d e - s w t r p
2)多表替换
多表替换即有多张原文密文对照表单,不同字母可以用不同表单的内容替换。
例如约定好表单为:表单 1:abcde-swtrp 、表单2:abcde-chfhk 、表单 3:abcde-jftou。规定第一个字母用第三张表单,第二个字母用第一张表单,第三个字母用第二张表单,这时 bee单词就变成了(312)fpk ,破解难度更高,其中 312 又叫做密钥,密钥可以事先约定好,也可以在传输过程中标记出来。

移位法

移位法就是将原文中的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移后得出密文,典型的移位法应用有 “ 恺撒密码 ”。
例如约定好向后移动2位(abcde - cdefg),这样 bee 单词就变换成了dgg
移位法也可以采用多表移位的方式,典型的多表案例是“维尼吉亚密码”(又译维热纳尔密码),属于多表密码的一种形式
古典密码的破解
古典密码虽然很简单,但是在密码史上是使用的最久的加密方式,直到“概率论”的数学方法被发现,古典密码就被破解了

近代密码学(1949年~1975年)

密码学真正成为一门科学
恩尼格玛机
恩尼格玛机使用的加密方式本质上还是移位和替代,只不过因为密码表种类极多,破解难度高,同时加密解密机器化,使用便捷,因而在二战时期得以使用。
恩尼格玛机是二战时期纳粹德国使用的加密机器,后被英国破译,参与破译的人员有被称为计算机科学之父、人工智能之父的图灵。

现代密码学(1976年以后)

密码学的新方向-公钥密码学,解决了秘钥分发和管理的问题
散列函数
散列函数,也见杂凑函数、摘要函数或哈希函数,可将任意长度的消息经过运算,变成固定长度数值,常见的有MD5、SHA-1、SHA256,多应用在文件校验,数字签名中。
MD5 可以将任意长度的原文生成一个128位(16字节)的哈希值
SHA-1可以将任意长度的原文生成一个160位(20字节)的哈希值
对称加密
对称密码应用了相同的加密密钥和解密密钥。对称密码分为:序列密码(流密码),分组密码(块密码)两种。流密码是对信息流中的每一个元素(一个字母或一个比特)作为基本的处理单元进行加密,块密码是先对信息流分块,再对每一块分别加密。
例如:原文为1234567890,流加密即先对1进行加密,再对2进行加密,再对3进行加密……最后拼接成密文;块加密先分成不同的块,如1234成块,5678成块,90XX(XX为补位数字)成块,再分别对不同块进行加密,最后拼接成密文。前文提到的古典密码学加密方法,都属于流加密。
对称密码的密钥安全极其重要,加密者和解密者需要提前协商密钥,并各自确保密钥的安全性,一但密钥泄露,即使算法是安全的也无法保障原文信息的私密性。

非对称加密

在实际的使用中,远程的提前协商密钥不容易实现,即使协商好,在远程传输过程中也容易被他人获取,因此非对称密钥此时就凸显出了优势。
非对称密码有两支密钥,公钥(publickey)和私钥(privatekey),加密和解密运算使用的密钥不同。用公钥对原文进行加密后,需要由私钥进行解密;用私钥对原文进行加密后(此时一般称为签名),需要由公钥进行解密(此时一般称为验签)。公钥可以公开的,大家使用公钥对信息进行加密,再发送给私钥的持有者,私钥持有者使用私钥对信息进行解密,获得信息原文。因为私钥只有单一人持有,因此不用担心被他人解密获取信息原文。

ASCII编码

ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是现今最通用的单字节编码系统,并等同于国际标准ISO/IEC 646
在这里插入图片描述

Base64可视化算法

Base64是网络上最常见的用于传输8Bit字节码的可读性编码算法之一

  1. 可读性编码算法不是为了保护数据的安全性,而是为了可读性
  2. 可读性编码不改变信息内容,只改变信息内容的表现形式
  3. 所谓Base64 即是说在编码过程中使用了64种字符:大写A到Z、小写a到z、数字0到9、“+”和“/”
  4. Base58是Bitcoin(比特币)中使用的一种编码方式,主要用于产生Bitcoin的钱包地址
    相比Base64,Base58不使用数字"0",字母大写"O",字母大写"I",和字母小写"i",以及"+“和”/"符号

算法原理

base64 是 3个字节为一组,一个字节 8位,一共 就是24位 ,然后,把3个字节转成4组,每组6位,3 * 8 = 4 * 6 = 24 ,每组6位,缺少的2位,会在高位进行补0 ,这样做的好处在于 ,base取的是后面6位,去掉高2位 ,那么base64的取值就可以控制在0-63位了,所以就叫base64。0~63在asc码表中正好对应上述64中字符。

注意,因为base64是三个字节一组 ,如果当我们的位数不够(三个字节)的时候,会使用等号来补齐。因此处理结果可能会出现=号

在这里插入图片描述 这里分析 “1” encode 过程:

  1. 字符 1asci码49 二进制表示为: 00110001
  2. 三个字节拆分为四个字节 这里只有一个字节,所以只能拆分成两个(不足的时候补0): 001100 010000
  3. 拆分后连个字节分别为:12 (M) 和 16(Q)
  4. 因为只有一个字节不足三个字节,因此必须进行补位,后边必须补两个“=” ,因此decode结果是: MQ==

对称加密

采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密。
特点
高效:加密速度快, 可以加密大文件密文可逆,
不足:秘钥无法管理复杂,一旦密钥文件泄漏, 就会导致数据暴露。
常见算法
DES : Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),并授权在非密级政府通信中使用,随后该算法在国际上广泛流传开来。
AES : Advanced Encryption Standard, 高级加密标准 .在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。
其他还有 3DES、IDEA

示例

public static void main(String[] args) throws Exception {
	 String key = "12345465";//des key 必须8位
	 String input = "zhansan";
	 String transformation = "DES";
	 String algorithm = "DES";
	 String ers= encryptDES(input,key,transformation,algorithm);
	 System.out.println(ers);
	 String rrr = decryptDES(ers, key, transformation, algorithm);
	 System.out.println(rrr);
	//使用AES加解密
	 key = "1234546511111111";//aes 算法 key 必须是16位
	 transformation = "AES";
	 algorithm = "AES";
	 ers= encryptDES(input,key,transformation,algorithm);
	 System.out.println(ers);
	 rrr = decryptDES(ers, key, transformation, algorithm);
	 System.out.println(rrr);
}
/**
 * 使用DES加密数据
*
 * @param input          : 原文
 * @param key            : 密钥(DES,密钥的长度必须是8个字节)
 * @param transformation : 获取Cipher对象的算法
 * @param algorithm      : 获取密钥的算法
 * @return : 密文
 * @throws Exception
 */
private static String encryptDES(String input, String key, String transformation, String algorithm) throws Exception {
    // 获取加密对象
    Cipher cipher = Cipher.getInstance(transformation);
    // 创建加密规则
    // 第一个参数key的字节
    // 第二个参数表示加密算法
    SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
    // ENCRYPT_MODE:加密模式
    // DECRYPT_MODE: 解密模式
    // 初始化加密模式和算法
    cipher.init(Cipher.ENCRYPT_MODE,sks);
    // 加密
    byte[] bytes = cipher.doFinal(input.getBytes());
    // 输出加密后的数据
    String encode = Base64.encode(bytes);
    return encode;
}

/**
 * 使用DES解密
 *
 * @param input          : 密文
 * @param key            : 密钥
 * @param transformation : 获取Cipher对象的算法
 * @param algorithm      : 获取密钥的算法
 * @throws Exception
 * @return: 原文
 */
private static String decryptDES(String input, String key, String transformation, String algorithm) throws Exception {
    // 1,获取Cipher对象
    Cipher cipher = Cipher.getInstance(transformation);
    // 指定密钥规则
    SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
    cipher.init(Cipher.DECRYPT_MODE, sks);
    // 3. 解密,上面使用的base64编码,下面直接用密文
    byte[] bytes = cipher.doFinal(Base64.decode(input));
    //  因为是明文,所以直接返回
    return new String(bytes);
}

加密模式和填充模式

加密模式
ECB : Electronic codebook, 电子密码本. 需要加密的消息按照块密码的块大小被分为数个块,并对每个块进行独立加密,同时加密,原文是一样的,加密出来的密文也是一样的
在这里插入图片描述

优点 : 可以并行处理数据
缺点 : 同样的原文生成同样的密文, 不能很好的保护数据

CBC : Cipher-block chaining, 密码块链接. 每个明文块先与前一个密文块进行异或后,再进行加密。在这种方法中,每个密文块都依赖于它前面的所有明文块
在这里插入图片描述
优点 : 同样的原文生成的密文不一样
缺点 : 串行处理数据.

填充模式
当需要按块处理的数据, 数据长度不符合块处理需求时, 按照一定的方法填充满块长的规则
NoPadding
不填充.在DES加密算法下, 要求原文长度必须是8byte的整数倍在AES加密算法下, 要求原文长度必须是16byte的整数倍。否则报错
PKCS5Padding
数据块的大小为8位, 不够就补足
默认情况下, 加密模式和填充模式为 : ECB/PKCS5Padding如果使用CBC模式, 在初始化Cipher对象时, 需要增加参数, 初始化向量IV : IvParameterSpec iv = new IvParameterSpec(key.getBytes());

加密模式和填充模式

AES/CBC/NoPadding (128)
AES/CBC/PKCS5Padding (128)
AES/ECB/NoPadding (128)
AES/ECB/PKCS5Padding (128)
DES/CBC/NoPadding (56)
DES/CBC/PKCS5Padding (56)
DES/ECB/NoPadding (56)
DES/ECB/PKCS5Padding (56)
DESede/CBC/NoPadding (168)
DESede/CBC/PKCS5Padding (168)
DESede/ECB/NoPadding (168)
DESede/ECB/PKCS5Padding (168)
RSA/ECB/PKCS1Padding (1024, 2048)
RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024, 2048)
RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024, 2048)

示例:

import com.sun.org.apache.xml.internal.security.utils.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class DesDemo {
    
    // DES加密算法,key的大小必须是8个字节

    public static void main(String[] args) throws Exception {
    
        String input ="ceshi";
        // DES加密算法,key的大小必须是8个字节
        String key = "12345678";
        // 指定获取Cipher的算法,如果没有指定加密模式和填充模式,ECB/PKCS5Padding就是默认值
        //     String transformation = "DES"; // 9PQXVUIhaaQ=
        //String transformation = "DES/ECB/PKCS5Padding"; // 9PQXVUIhaaQ=
        // CBC模式,必须指定初始向量,初始向量中密钥的长度必须是8个字节
        //String transformation = "DES/CBC/PKCS5Padding"; // 9PQXVUIhaaQ=
        // NoPadding模式,原文的长度必须是8个字节的整倍数 ,所以必须把 硅谷改成硅谷12
        String transformation = "DES/CBC/NoPadding"; // 9PQXVUIhaaQ=
        // 指定获取密钥的算法
        String algorithm = "DES";
        String encryptDES = encryptDES(input, key, transformation, algorithm);
        System.out.println("加密:" + encryptDES);
//        String s = dncryptDES(encryptDES, key, transformation, algorithm);
//        System.out.println("解密:" + s);

    }

    /**
     * 使用DES加密数据
     *
     * @param input          : 原文
     * @param key            : 密钥(DES,密钥的长度必须是8个字节)
     * @param transformation : 获取Cipher对象的算法
     * @param algorithm      : 获取密钥的算法
     * @return : 密文
     * @throws Exception
     */
    private static String encryptDES(String input, String key, String transformation, String algorithm) throws Exception {
    
        // 获取加密对象
        Cipher cipher = Cipher.getInstance(transformation);
        // 创建加密规则
        // 第一个参数key的字节
        // 第二个参数表示加密算法
        SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
        // ENCRYPT_MODE:加密模式
        // DECRYPT_MODE: 解密模式
         // 初始向量,参数表示跟谁进行异或,初始向量的长度必须是8位
//        IvParameterSpec iv = new IvParameterSpec(key.getBytes());
         // 初始化加密模式和算法
        cipher.init(Cipher.ENCRYPT_MODE,sks);
        // 加密
        byte[] bytes = cipher.doFinal(input.getBytes());
        // 输出加密后的数据
        String encode = Base64.encode(bytes);
        return encode;
    }

    /**
     * 使用DES解密
     *
     * @param input          : 密文
     * @param key            : 密钥
     * @param transformation : 获取Cipher对象的算法
     * @param algorithm      : 获取密钥的算法
     * @throws Exception
     * @return: 原文
     */
    private static String dncryptDES(String input, String key, String transformation, String algorithm) throws Exception {
    
        // 1,获取Cipher对象
        Cipher cipher = Cipher.getInstance(transformation);
        // 指定密钥规则
        SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
//        IvParameterSpec iv = new IvParameterSpec(key.getBytes());
        cipher.init(Cipher.DECRYPT_MODE, sks);
        // 3. 解密
        byte[] bytes = cipher.doFinal(Base64.decode(input));
        return new String(bytes);
    }
}

摘要算法

又称为消息摘要(Message Digest)或数字摘要(Digital Digest)
它由一个单向Hash加密函数对消息进行计算得到一个定长的字符串。
特点:

  1. 消息摘要是单向、不可逆的
  2. 无论输入的消息有多长,计算出来的消息摘要的长度总是固定的。例如应用MD5算法摘要的消息有128个比特位,用SHA-1算法摘要的消息最终有160比特位的输出
    常见算法:
  • MD5
  • SHA1
  • SHA256
  • SHA512

示例

public class DigestDemo1 {
    
    public static void main(String[] args) throws Exception{
    
        // 原文
        String input = "aa";
        // 算法
        String algorithm = "MD5";
        // 获取数字摘要对象
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        // 消息数字摘要
        byte[] digest = messageDigest.digest(input.getBytes());
//        System.out.println(new String(digest));
        // base64编码
        System.out.println(Base64.encode(digest));
    }
}

非对称加密

非对称加密算法又称现代加密算法。 是计算机通信安全的基石,保证了加密数据不会被破解。 与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey) 和私有密(privatekey),公开密钥和私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密。如果用私有密钥对数据进行加密,只有用对应的公开密钥才能解密。 因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。
在这里插入图片描述
特点
加密和解密使用不同的密钥,解决秘钥传递的问题
如果使用私钥加密, 只能使用公钥解密
如果使用公钥加密, 只能使用私钥解密
处理数据的速度较慢, 因为安全级别高
常见算法
RSA、ECC、EIGamal
生成公钥私钥示例

/**
     * 生成密钥对并保存在本地文件中
     *
     * @param algorithm : 算法
     * @param pubPath   : 公钥保存路径
     * @param priPath   : 私钥保存路径
     * @throws Exception
     */
    public static void generateKeyToFile(String algorithm, String pubPath, String priPath) throws Exception {
        // 加密算法
        //String algorithm = "RSA";
        //  创建密钥对生成器对象
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
        // 生成密钥对
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        // 生成私钥
        PrivateKey privateKey = keyPair.getPrivate();
        // 生成公钥
        PublicKey publicKey = keyPair.getPublic();
        // 获取私钥字节数组
        byte[] privateKeyEncoded = privateKey.getEncoded();
        // 获取公钥字节数组
        byte[] publicKeyEncoded = publicKey.getEncoded();
        // 对公私钥进行base64编码
        String privateKeyString = Base64.encode(privateKeyEncoded);
        String publicKeyString = Base64.encode(publicKeyEncoded);
        // 打印私钥
        System.out.println(privateKeyString);
        // 打印公钥
        System.out.println(publicKeyString);

        // 保存文件
        writeStringToFile(new File(pubPath), publicKeyString, Charset.forName("UTF-8"));
        writeStringToFile(new File(priPath), privateKeyString, Charset.forName("UTF-8"));
    }

加解密示例示例

  public static void test04()  throws Exception {
        String input = "测试字符串";
        // 加密算法
        String algorithm = "RSA";
        PrivateKey privateKey = getPrivateKey("C:\\Users\\pcitc\\IdeaProjects\\testPro\\src\\main\\java\\a.pri", algorithm);
        PublicKey publicKey = getPublicKey("C:\\Users\\pcitc\\IdeaProjects\\testPro\\src\\main\\java\\a.pub", algorithm);
        //私钥加密
        String s = encryptRSA(algorithm, privateKey, input);
        System.out.println("====》私钥加密结果:"+s);
        //公钥解密
        String s1 = decryptRSA(algorithm, publicKey, s);
        System.out.println("====》公钥解密结果:"+s1);

        //公钥加密
         s = encryptRSA(algorithm,  publicKey, input);
        System.out.println("====》公钥加密结果:"+s);
        //私钥解密
        s1 = decryptRSA(algorithm, privateKey, s);
        System.out.println("====》私钥解密结果:"+s1);

//        //公钥加密
//        s = encryptRSA(algorithm, publicKey, input);
//        System.out.println("====》公钥加密结果:"+s);
//        //公钥解密   公钥加密结果公钥解密辉报错 BadPaddingException
//        s1 = decryptRSA(algorithm, publicKey, s);
//        System.out.println("====》私钥解密结果:"+s1);
    }

    /**
     * 写入到文件
     * @param file
     * @param publicKeyString
     * @param forName
     * @throws Exception
     */
    private static void writeStringToFile(File file, String publicKeyString, Charset forName) throws Exception {
        System.out.println("文件路径==>"+file.getAbsolutePath());

        FileOutputStream fileOutputStream = null;
        try{
            fileOutputStream = new FileOutputStream(file);
            fileOutputStream.write(publicKeyString.getBytes(forName));

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            fileOutputStream.close();
        }
    }

    public static PrivateKey getPrivateKey(String priPath,String algorithm) throws Exception{
        // 将文件内容转为字符串
        String privateKeyString = readFileToString(new File(priPath), Charset.defaultCharset());
        // 获取密钥工厂
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        // 构建密钥规范 进行Base64解码
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(Base64.decode(privateKeyString));
        // 生成私钥
        return keyFactory.generatePrivate(spec);
    }

    public static PublicKey getPublicKey(String pulickPath,String algorithm) throws Exception{
        // 将文件内容转为字符串
        String publicKeyString = readFileToString(new File(pulickPath), Charset.defaultCharset());
        // 获取密钥工厂
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        // 构建密钥规范 进行Base64解码
        X509EncodedKeySpec spec = new X509EncodedKeySpec(Base64.decode(publicKeyString));
        // 生成公钥
        return keyFactory.generatePublic(spec);
    }
    private static String readFileToString(File file, Charset defaultCharset) throws Exception {
        //FileInputStream fileInputStream = new FileInputStream(file);
        InputStreamReader read = new InputStreamReader(new FileInputStream(file),defaultCharset);//考虑到编码格式
        StringBuffer sb = new StringBuffer();
        try{
            BufferedReader bufferedReader = new BufferedReader(read);
            String lineTxt = null;
            while((lineTxt = bufferedReader.readLine()) != null){
                //System.out.println(lineTxt);
                sb.append(lineTxt);
            }
            return sb.toString();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            read.close();
        }
        return sb.toString();
    }
    /**
     * 解密数据
     *
     * @param algorithm      : 算法
     * @param encrypted      : 密文
     * @param key            : 密钥
     * @return : 原文
     * @throws Exception
     */
    public static String decryptRSA(String algorithm,Key key,String encrypted) throws Exception{
        // 创建加密对象
        // 参数表示加密算法
        Cipher cipher = Cipher.getInstance(algorithm);
        // 私钥进行解密
        cipher.init(Cipher.DECRYPT_MODE,key);
        // 由于密文进行了Base64编码, 在这里需要进行解码
        byte[] decode = Base64.decode(encrypted);
        // 对密文进行解密,不需要使用base64,因为原文不会乱码
        byte[] bytes1 = cipher.doFinal(decode);
        return new String(bytes1);

    }
    /**
     * 使用密钥加密数据
     *
     * @param algorithm      : 算法
     * @param input          : 原文
     * @param key            : 密钥
     * @return : 密文
     * @throws Exception
     */
    public static String encryptRSA(String algorithm,Key key,String input) throws Exception{
        // 创建加密对象
        // 参数表示加密算法
        Cipher cipher = Cipher.getInstance(algorithm);
        // 初始化加密
        // 第一个参数:加密的模式
        // 第二个参数:使用私钥进行加密
        cipher.init(Cipher.ENCRYPT_MODE,key);
        // 私钥加密
        byte[] bytes = cipher.doFinal(input.getBytes());
        // 对密文进行Base64编码
        return Base64.encode(bytes);
    }

数字签名

数字签名(又称公钥数字签名)是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。它是一种类似写在纸上的普通的物理签名,但是使用了公钥加密领域的技术来实现的,用于鉴别数字信息的方法。
数字签名是非对称密钥加密技术(私钥加密只有公钥能解密)与数字摘要技术的应用。
数字签名的主要作用就是保证了数据的有效性(验证是谁发的)和完整性。比如电子合同,就跟纸质合同一样。有这个数字签名就可以进行验证合同是你签的且合同没有被私自改动过(就和纸质合同上签名盖章一样)
如下:使用非对称加密和摘要算法,实现一个甲方张三给乙方李四投资的电子合同。
合同内容:甲方 张三投资1个亿给李四。 需要甲方张三进行数字签名

  1. 甲方张三有自己的一对公钥和秘钥。私钥自己持有(不可泄露),公钥分发给大家(包括李四)
  2. 首先采用摘要算法将合同内容进行摘要计算,假如摘要结果为:“DE81…1TE2”
  3. 甲方张三采用私钥对摘要结果进行加密,假设加密结果为"2ERT33…UI9",那么这个加密结果就是张三的数字签名。
  4. 乙方李四持有甲方的公钥,拿到甲方的签名后,可以对数字签名进行验证,使用甲方公钥对数字签名进行解密,得到合同内容摘要(能用甲方公钥解密证明是甲方签的,其他人不可能有甲方私钥),然后对合同内容再次进行摘要计算,对比得到的摘要结果和解密甲方数字签名得到的摘要结果是否相同。如果相同,那么证明该合同未被篡改过且肯定是甲方签名的。
    在这里插入图片描述

数字证书

对数字签名进行验证时,需要用到公钥。如果公钥是伪造的,那我们无法验证数字签名了,也就根本不可能从数字签名确定对方的合法性了。如何保证自己拿到的公钥是合法的而不是被别人伪造的呢?这就是数字证书要实现的功能。数字证书可以保证公钥信息的可信。

如果我们只拿到一个公钥信息,就无法确认该信息是否合法(未被篡改过),如果除了公钥信息我们同时拿到了权威机构数字签名,(根据上文中数字签名的作用)那么这个公钥就十分可信了。
就像我们只有一个四级证书上面没有教育部的章,那么这个证书只是一张纸谁都可以印,但是上边加盖了教育部的(不可伪造的)印章,那么这张证书就会变的很可信。

总结:数字证书就是由(可信的)权威机构签发的,带有权威机构签名(不可伪造和篡改)的公钥信息。
证书的产生和管理
PKI
PKI是一个包括硬件、软件、人员、策略和规程的集合,用来实现基于公钥密码体制的密钥和证书的
产生、管理、存储、分发和撤销等功能。
PKI架构

  1. CA(认证权威):
    证书的发证机构,负责签发、更新、管理(撤销、查询、审计)证书,验证证书合法性(是否在黑名单、是否合法等)。如果用户想开通一个网站生成自己的证书可以向CA发起申请。
  2. RA(注册权威):受理用户的数字证书申请,协助CA验证核实证书申请者的信息,如果验证合法,则提交CA制证。
  3. 证书存放管理(目录服务):
    证书的存储库,提供证书的存储、修改、删除、获取的能力。如:一共签发了1000套证书,那么这些证书都在证书库中。
  4. 终端实体(证书持有者和应用程序):
    拥有公钥、私钥的用户,可以根据需要申请自己的证书。可以是人、设备、进程

CA 也分为不同级别,需要逐级验证。比如 CA1 不被大家信任,于是可以将身份信息和公钥发送给受信任的 CA2,获得自己的数字证书。CA1 在给其他人签署数字证书时,会在后面附上自己的数字证书这样接受者首先利用 CA2 的公钥验证 CA1,获得 CA1 的公钥后再验证发送者这样逐级签署数字证书,形成了一条信任链,最终的根节点就是自签名证书,如 CA2 可以用自己的私钥把自己的公钥和域名加密,生成证书。

在这里插入图片描述
证书的格式
国际标准X.509定义了电子证书的规范格式,包括拥有者身份信息和公开密钥的数据体、经证书权威机构CA的数字签名等内容
在这里插入图片描述

SSL、TLS 、HTTP和HTTPS

SSL:(Secure Socket Layer,安全套接字层)为Netscape所研发,用以保障在Internet上数据传输之安全,利用数据加密(Encryption)技术,SSL通过互相认证、使用数字签名确保完整性、使用加密确保私密性,以实现客户端和服务器之间的安全通讯。该协议由两层组成:SSL记录协议和SSL握手协议。握手协议用来协商密钥。 记录协议则定义了传输的格式。
TLS:(Transport Layer Security,传输层安全协议),用于两个应用程序之间提供保密性和数据完整性。该协议由两层组成:TLS记录协议和TLS握手协议。最新版本的TLS 1.0是IETE(工程任务组)指定的一种新的协议,它建立在SSL 3.0协议规范之上,是SSL 3.0的后续版本。两者差别极小,可以理解为SSL 3.1,它是写入了RFC的。
两者作用

  1. 认证用户和服务器,确保数据发送到正确的客户机和服务器,SSL缺省只进行server端的认证,客户端的认证是可选的
  2. 加密数据以防止数据中途被窃取;
  3. 维护数据的完整性,确保数据在传输过程中不被改变

握手协议
如上所述。握手协议就是双方通过公钥算法协商出一份密钥,然后通过对称加密来通信。握手过程如下:
在这里插入图片描述
SSL客户端(也是TCP的客户端)在TCP链接建立之后,发出一个ClientHello来发起握手,这个消息里面包含了自己可实现的算法列表和其它一些需要的消息,SSL的服务器端会回应一个ServerHello,这里面确定了这次通信所需要的算法,然后发过去自己的证书(里面包含了身份和自己的公钥)。Client在收到这个消息后会生成一个秘密消息,用SSL服务器的公钥加密后传过去,SSL服务器端用自己的私钥解密后,会话密钥协商成功,双方可以用同一份会话密钥来通信了。

HTTP和HTTPS
HTTP 是一种协议,全称叫作:超文本传输协议(HTTP,HyperText Transfer Protocol),是互联网上应用最为广泛的一种网络协议。所有的 WWW 文件都必须遵守这个标准。
HTTPS 也是一种超文本传送协议,(HTTPS,Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的 HTTP 通道,简单讲是 HTTP 的安全版。即 HTTP 下加入 SSL 层,HTTPS 的安全基础是 SSL,因此加密的详细内容就需要 SSL。用于安全的 HTTP 数据传输。
HTTPS 和 HTTP 的区别主要为以下四点:
https 协议需要到 ca 申请证书,目前市面上的免费证书也不少,收费的也都比较贵。
http 是超文本传输协议,信息是明文传输,https 则是具有安全性的 ssl 加密传输协议。
http 和 https 使用的是完全不同的连接方式,用的端口也不一样,前者是 80,后者是 443。
http 的连接很简单,是无状态的;HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 http 协议安全。
在这里插入图片描述

如果对你有帮助烦请顺手点个赞,这是对我最大的鼓励和认可

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zhangxm_qz/article/details/115876297

智能推荐

info级别日志与debug_debug中的计算是否在info级别也会跑-程序员宅基地

文章浏览阅读6.3k次。日志默认info级别debug日志不会打印,但是会执行日志填充的数据例如:logger.debug("日志输出",2*10); 1. 2*10会先执行出结果,然后继续往下走2. 在ch.qos.logback.classic.Logger#filterAndLog_1方法中判断是否符合级别要求是否需要输出3.如图:..._debug中的计算是否在info级别也会跑

Third calibration example - Calibration using Heikkil�'s data (planar and non-planar calibration rig-程序员宅基地

文章浏览阅读1.4k次。Similarly to the previous example, let us apply our calibration engine onto the data that comes with the originalcalibration toolbox of Heikkil� from the University of Oulu. Once again. do not bothe_non-planar calibration

物联网常用的网络协议:MQTT、AMQP、HTTP、CoAP、LwM2M_lmm2m和mqtt-程序员宅基地

文章浏览阅读1w次,点赞10次,收藏63次。物联网常用的网络协议:MQTT、AMQP、HTTP、CoAP、LwM2M物联网设备间沟通的语言,就是网络协议。设备间想相互交流,通信双方必须使用同一种“语言”。比如说你和中国人问好说’你好‘、日本人问好要说‘こんにちは’、和英国人问好要说‘hello’.说起网络协议,你可能马上就想到了 HTTP 协议。是的,在日常的 Web 开发中,我们总是需要跟它打交道,因为 HTTP 协议是互联网的主流网络协议。类似地,应用在互联网中的网络协议,还有收发电子邮件的 POP3 、SMTP 和 IMAP 协议,以及_lmm2m和mqtt

fortran使用MKL函数库中的geev计算一般矩阵的特征值与特征向量_fortran求矩阵特征值-程序员宅基地

文章浏览阅读7.4k次,点赞4次,收藏20次。这篇博文简要记录一下使用MKL函数库计算一般矩阵的特征值与特征向量对形如对称矩阵或是埃尔米特等特殊矩阵有其对应的子程序,在这里先不涉及。有需求的可以自行查阅MKL官方文档下面给出本次示例代码:代码使用f95接口。f77借口参数太多,笔者太懒<不过懒惰是创新的原动力^_^>program testGeev use lapack95 implicit..._fortran求矩阵特征值

Numpy, Scipy, Matplotlib基本用法_np.imresize-程序员宅基地

文章浏览阅读147次。学习内容来自:Numpy Tutorial文章目录Array SlicingArray IndexingMathematical ManipulationBroadcastingImage Processing基本的用法课程里面说的挺详细了。 特别记录一些需要关注的点。Array Slicing使用固定数字进行array寻址会导致数组降维。y = np.random.random((3,..._np.imresize

蓝桥杯 历届试题 回文数字 C++_c++蓝桥杯 回文数-程序员宅基地

文章浏览阅读355次。题目阅览 观察数字:12321,123321 都有一个共同的特征,无论从左到右读还是从右向左读,都是相同的。这样的数字叫做:回文数字。  本题要求你找到一些5位或6位的十进制数字。满足如下要求:  该数字的各个数位之和等于输入的整数。  输入格式  一个正整数 n (10<n<100), 表示要求满足的数位和。  输出格式若干行,每行包含一个满足要求的5位或6位整数。  数字按从小到大的顺序排列。  如果没有满足条件的,输出:-1样例输入144样例输出199899_c++蓝桥杯 回文数

随便推点

Java生成二维码,扫描并跳转到指定的网站_java扫二维码进入自己制作的网页-程序员宅基地

文章浏览阅读6.2k次,点赞3次,收藏13次。需要的pom文件 &lt;dependency&gt; &lt;groupId&gt;com.google.zxing&lt;/groupId&gt; &lt;artifactId&gt;core&lt;/artifactId&gt; &lt;version&gt;3.1.0&lt;/version&gt;_java扫二维码进入自己制作的网页

python:多波段遥感影像分离成单波段影像_一个多波段影像分解成多个单波段影像-程序员宅基地

文章浏览阅读650次。在遥感图像处理中,我们经常需要将多波段遥感影像拆分成多个单波段图像,以便进行各种分析和后续处理。本篇博客将介绍一个用Python编写的程序,该程序可以读取多波段遥感影像,将其拆分为单波段图像,并保存为单独的文件。本程序使用GDAL库来处理遥感影像数据,以及NumPy库来进行数组操作。结果如下图所示,选中的影像为输入的多波段影像,其他影像分别为拆分后的多波段影像。_一个多波段影像分解成多个单波段影像

移动硬盘突然在电脑上无法显示_电脑无法显示移动硬盘-程序员宅基地

文章浏览阅读5.1k次,点赞2次,收藏4次。0前言一直用的好好的移动硬盘突然不显示了,前段时间因为比较忙,一直没顾得上管它,趁这个假期,好好捅咕了一番,总算是弄好了,特此将解决的过程记录如下:1.问题描述 1.我的移动硬盘在其他人的电脑上能够正常显示和使用 2.其他移动硬盘在我电脑上能够正常的显示和使用 3.在我的电脑上,该移动硬盘,既不显示盘符,磁盘管理 又不显示该磁盘2.问题分析1.我的移动硬盘能够在其他人电脑上_电脑无法显示移动硬盘

Linux开机启动过程(16):start_kernel()->rest_init()启动成功_linux 标志着kernel启动完成-程序员宅基地

文章浏览阅读1k次。Kernel initialization. Part 10.在原文的基础上添加了5.10.13部分的源码解读。End of the linux kernel initialization processThis is tenth part of the chapter about linux kernel initialization process and in the previous part we saw the initialization of the RCU and stopped o_linux 标志着kernel启动完成

Scala安装和开发环境配置教程_scala安装及环境配置-程序员宅基地

文章浏览阅读5.3k次,点赞5次,收藏23次。Scala语言概述:Scala语言是一门以Java虚拟机为运行环境,支持面向对象和函数式编程的静态语言,java语言是面向对象的,所以代码写起来就会相对比较模块儿,而函数式编程语言相对比较简洁_scala安装及环境配置

深扒人脸识别60年技术发展史_人脸识别发展历史-程序员宅基地

文章浏览阅读2.4k次。“他来听我的演唱会,门票换了手铐一对”。最近歌神张学友变阿SIR,演唱会上频频抓到罪犯,将人脸识别技术又一次推到了大众的视线中。要说人脸识别技术的爆发,当属去年9月份苹果iPhone x的发布,不再需要指纹,只需要扫描面部就可以轻松解锁手机。任何技术一旦进入智能手机这个消费市场,尤其是被苹果这个标志性的品牌采用,就意味着它将成为一种趋势,一个智能设备的标配。在智能手机快速崛起的这几年,其密码锁..._人脸识别发展历史