PKI体系系列一

什么是PKI体系?

• PKI:公钥基础设施,Public Key Infrastructure
公钥基础设施是一个包括硬件、软件、人员、策略和规程的集合,用来实现基于公钥密码体制的密钥和证书的产生、管理、存储、分发和撤销等功能。是一种遵循既定标准的密钥管理平台,它能够为所有网络应用提供加密和数字签名等密码服务及所必需的密钥和证书管理体系。
• PKI指的是证书的制作和分发的一种机制。在这个机制的保障前提下,进行可信赖的网络通信。即安全的网路通信保障机制。PKI技术是信息安全技术的核心,也是电子商务的关键和基础技术。 PKI的基础技术包括加解密、数字签名、证书、数据完整性机制、数字信封、双重数字签名等。

典型PKI系统

• 典型的PKI就是在包含PKI策略和软硬件系统、以及在这基础之上建立的的CA证书机构、RA注册机构以及证书颁发系统上建立的一个应用。如图所示:
在这里插入图片描述

其中CA中心又称为证书认证机构、认证中心,是整个PKI体系的核心,是PKI的信任基础,它是可信的,具有权威性和公正性。CA的工作包含生成密钥对、注册证书、作废证书和CRL(证书作废清单)。
RA是证书认证体系中的一部分,主要接收来自用户的证书及CRL申请请求、核实用户的身份、转发CA颁发的证书和证书作废清单CRL等。
• 专门负责颁发数字证书的系统称为 CA 系统,负责管理并运营 CA 系统的机构称为 CA 中心。所有与数字证书相关的各种概念和技术,统称为 PKI(Public Key Infrastructure)。
更多内容可参考:https://baike.baidu.com/item/%E5%85%AC%E9%92%A5%E5%9F%BA%E7%A1%80%E8%AE%BE%E6%96%BD/10881894?fromtitle=PKI&fromid=212376&fr=aladdin

公钥密码算法–公钥加密,私钥解密

一、什么是公钥密码?

• 在查看对称密码一文中,我们可以发现,对称密码就是加密和解密使用同一把密钥,因此使用对称密码算法存在密钥的配送问题。但是公钥密码是与对称密码完全不同的一套体系,在公钥密码中,密钥都是成对出现的,即(公钥—public key,私钥—private key)。
• 公钥是公开的,任何人都可以获取到这个公钥,但是私钥却是私密的,私钥绝对不能公开,让其他人获取到这个 私钥。
• 一般情况下,在使用公钥密码的加解密体系时,我们使用公钥public key对明文数据进行加密,使用加密公钥对应的私钥private key对密文数据进行解密(公钥和私钥是一一对应的,一对公钥和私钥称为密钥对,该密钥对之间存在严密的数学关系,因此公钥和私钥不能 单独存在或产生)。
• 在实际应用中,如果消息的发送方和消息的接收方想要进行数据通讯,那么由消息的接收方或者可信的第三方(CA证书颁发机构等)产生密钥对,然后将公钥发送给消息的发送方,而私钥则自己保存或者存储在可信的第三方系统(CA系统)内,消息的接收方收到密文消息之后,使用该公钥对应的私钥对密文数据进行解密。即私钥是不可能出现在消息的发送方或者除消息的接收方及可信第三方之外的人手中。这样就保证了密钥的安全性,从而保证我们加密数据的安全性。(因为,即使公钥公开,被窃听者窃听到,但是他拿不到该公钥对应的私钥,那么他依旧没有办法对数据进行解密,进而拿到数据正确的明文信息而导致消息的泄露~)

二、公钥密码加解密通信流程

• 假设现在Alice(消息的发送者)和Bob(消息的接收者)之间要进行数据通信,那么他们之间的通信流程如图所示:
• ①要进行通信,就得先有密钥对。Bob生成一个包含公钥和私钥的密钥对,公钥通过信道发送给Alice,而私钥则Bob自己保存。
• ②Alice收到Bob发送的公钥之后,即可用这把公钥将需要发送给Bob的消息进行加密 ,然后将加密的密文结果发送给Bob------该密文只有Bob手中的私钥才能解密,其他私钥都不能将该密文信息解开。
• ③Bob收到Alice发送的密文信息,然后用自己手中的私钥对密文信息进行解密,这样即可得到Alice发送的明文信息。
在这里插入图片描述

• 而在以上三个步骤中,即使窃听者窃听了通过信道发送的公钥和数据密文,他也没办法对数据进行解密,即数据在信道上是安全的,当然,我们不能说只要使用了公钥加解密算法,我们的消息就一定安全了,虽然加密公钥对应的私钥只有Bob自己有,但是我们不能排除Bob将私钥偷偷发送给被人的可能,也不能排除有人偷偷从Bob那里看到了私钥的可能 (如社会工程学的攻击)。
• 其实公钥密码算法还存在中间人攻击的可能性—这个问题称为公钥的认证问题(可以用证书、消息认证码、数字签名等方法来进行验证)。即存在中间人Eve,在Bob将公钥发送给Alice的过程在,Eve窃听了Bob和Alice的通信,在Eve拿到信道上的公钥之后,将Bob的公钥替换成自己生的密钥对中的公钥,然后将其发送给Alice,Alice收到公钥之后,会以为这是Bob的,但其实是Eve的。在Alice用Eve的公钥加密之后将密文发送给Bob的时候,Eve用自己的私钥解密拿到Alice发送的明文,然后再用Bob发送的公钥对解密后的数据加密之后在外送给Bob,在这个过程中,Bob能解开数据。但其实攻击者Eve已经拿到了消息的明文,而Alice和Bob却浑然不知~

三、公钥加密算法—RSA

• RSA是一种公钥密码算法,它的名字是由它的三未开发者即Ron Rivest、Adi Shamir和Leonard Adleman的姓氏的首字母组成的。
• 其实RSA即可以用来数据的加解密运算,也可以用来做数字签名使用,关于数字签名相关的内容,我会在下个知识点进行讲解。

1、RSA算法实质

• RSA算法实质上是模逆运算的应用。
RSA公开密钥密码体制所根据的原理是:根据数论,寻求俩个大素数比较简单,而将它们的乘积分解开则极其困难。比如在一个有限的范围内,很容易计算出数字的乘积,但是却很难分解出生成那个乘积的各个乘数。
和DES一样的是,RSA也是分组加密算法,不同的是分组大小可以根据秘钥的大小而改变。如果加密的数据不是分组大小的整数倍,则会根据具体的应用方式增加额外的填充位。
RSA作为一种非对称的加密算法,其中最重要的一个特点就是当数据在网络中传输时,用来加密数据的秘钥并不需要也和数据一起传送,这样就减少了秘钥泄露的可能性。加密的一方使用的秘钥称为公钥,解密方使用的秘钥称为私钥,在进行RSA加解密的时候,需要保证私钥的安全性和私有性。
RSA被认为是非常安全的,但是他的计算速度比DES慢很多,同DES一样,其安全性也从未被证明过,但是想要破解RSA算法涉及的大数(至少200位)的因子分解是一个极其困难的问题,所以由于缺乏大数因子分解的有效方法,可以推测出目前没有有效的办法可以破解RSA。
RSA算法基于的原理,基本上来说,加密和解密数据都是围绕模幂运算。取模运算就是x mod
n的结果等于x/n的余数,而模幂运算即就算a^b mod n的过程。

2、RSA算法的过程

• RSA加解密的过程就是:模运算的结果作为加密后的密文信息,模运算的逆运算结果作为解密后的明文信息。

在RSA算法中,每个用户拥有俩个密钥:公开密钥PK和秘密秘钥SK。
公开密钥PK={e,n}用于加密,也称为加密密钥,可以公布在网络、电话簿等媒体上。
秘密密钥SK={d,n}用于解密,也称为解密密钥,必须保密。
用户把加密密钥PK公开,使得系统中的任何其他用户都可以使用,而对解密密钥SK中的d则必须保密。
(1)密钥产生
①用户秘密的选择俩个大素数p和q(p和q一般为100位以上的十进制数)。
②计算n=p*q。n称为RSA算法的模数。
③计算φ=(p-1)*(q-1)。
④选择数e。用户从[0,φ-1]中选择一个与φ互质的数e作为公开的加密指数。
⑤计算d。用户计算出满足(e*d) mod φ=1的d作为解密指数。
⑥选好这些参数后,得出所需的公开密钥和秘密密钥。
(2)加密/解密算法。


将明文划分成块,每块明文报文长度为m(0<m<n)。
利用公开密钥PK={e,n}对明文m加密,C为加密后的密文,即:
       C=m^e mod n
利用秘密密钥SK={d,n}对密文C解密,m为解密后的明文,即:
       m=C^d mod  n
由于模运算的对称性,因此可以证明加密和解密在一定范围内是可逆的。

3、Java中RSA算法工具代码解析

1)产生密钥对

• 接口在java.security.KeyPairGenerator中,代码实现可参照以下实现。
• 据我网上查阅资料,KeyPairGenerator.getInstance的入参可以是RSA/DSA(1024)/DiffieHellman,其中RSA的密钥长度从512-65536之间,且必须是64的整数倍

 /**
     * 生成秘钥对
     * @return 密钥对对象
     * @throws Exception
     */
    public static KeyPair getKeyPair() throws Exception {
        //指定产生的密钥对是RSA的密钥对
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        //生成的密钥长度,其中RSA的密钥长度从512-65536之间,且必须是64的整数倍
        keyPairGenerator.initialize(2048);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        return keyPair;
    }
KeyPairGenerator类用于生成公钥和私钥对。 密钥对生成器使用getInstance工厂方法(返回给定类的实例的静态方法)构造。 
用于特定算法的密钥对生成器创建可以与该算法一起使用的公钥/私钥对。 它还将算法特定的参数与生成的每个密钥相关联。 
生成密钥对的方法有两种:以算法无关的方式,并以算法特定的方式。 两者之间的唯一区别是对象的初始化: 
独立于算法的初始化 
所有密钥对生成器共享密钥大小和随机源的概念。 对于不同的算法来说,keyize被不同地解释(例如,在DSA算法的情况下,keysize对应于模数的长度)。 此KeyPairGenerator类中有一个initialize方法,它接受这两个普遍共享的参数类型。 还有一个只带有keysize参数,并使用SecureRandom实现的最高优先级安装的提供作为随机源。 (如果没有一个已安装的提供商提供SecureRandom的SecureRandom ,则使用系统提供的随机源。) 
由于在调用上述与算法无关的initialize方法时没有指定其他参数,因此提供者如何处理与每个密钥相关联的特定于算法的参数(如果有的话)。 
如果算法是DSA算法和密钥大小(模数的大小)为512768,或1024,那么Sun提供使用为一组预先计算的值的p , q和g参数。 如果模数大小不是上述值之一, Sun提供商将创建一组新的参数。 其他提供商可能预先计算的参数集超过上述三个模数大小。 还有一些可能没有预先计算的参数的列表,而不是总是创建新的参数集。 
特定于算法的初始化 
对于已经存在一组特定于算法的参数(例如,DSA中所谓的社区参数 )的情况,有两种initialize方法具有AlgorithmParameterSpec参数。 其中也有一个SecureRandom的说法,而其他使用SecureRandom实现的最高优先级安装的提供作为随机源。 (如果没有一个安装的提供商提供SecureRandom的SecureRandom ,则使用系统提供的随机源。) 
如果客户端没有显式初始化KeyPairGenerator(通过调用initialize方法),则每个提供程序都必须提供(并记录)默认的初始化。 例如, Sun提供商使用1024位的默认模数大小(keysize)。 
注意,这个类是抽象的,由于历史原因而从KeyPairGeneratorSpi延伸。 应用程序开发人员只应注意本KeyPairGenerator课程中定义的方法; 超类中的所有方法都适用于希望提供自己的密钥对生成器实现的加密服务提供商。 
Java平台的每个实现都需要支持以下标准KeyPairGenerator算法,并在括号中键入: 
DiffieHellman (1024) 
DSA (1024) 
RSA ( RSA ) 
更多JDK1.8加解密相关内容,可参考链接: https://pan.baidu.com/s/1x78oIclh564zmwRp9bpTkA 提取码: spgr
2)公私钥对象封装
/**
     * 获取公钥(Base64编码)
     * @param keyPair getKeyPair返回值
     * @return 公钥的base64编码
     */
    public static String getPublicKey(KeyPair keyPair) {
        PublicKey publicKey = keyPair.getPublic();
        byte[] bytes = publicKey.getEncoded();
        return byte2Base64(bytes);
    }
    /**
     * 获取私钥(Base64编码)
     * @param keyPair getKeyPair返回值
     * @return 私钥的base64编码
     */
    public static String getPrivateKey(KeyPair keyPair) {
        PrivateKey privateKey = keyPair.getPrivate();
        byte[] bytes = privateKey.getEncoded();
        return byte2Base64(bytes);
    }
    /**
     * 将Base64编码后的公钥转换成PublicKey对象
     * @param pubStr 公钥base64编码
     * @return 公钥对象
     * @throws Exception
     */
    public static PublicKey string2PublicKey(String pubStr) throws Exception {
        byte[] keyBytes = base642Byte(pubStr);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        return publicKey;
    }
    /**
     * 将Base64编码后的私钥转换成PrivateKey对象
     * @param priStr 私钥base64编码
     * @return 公钥对象
     * @throws Exception
     */
    public static PrivateKey string2PrivateKey(String priStr) throws Exception {
        byte[] keyBytes = base642Byte(priStr);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
    }
3)RSA加解密

```java
/**
     * 公钥加密
     * @param content 待加密的内容
     * @param publicKey 公钥对象
     * @return 加密结果
     * @throws Exception
     */
    public static byte[] publicEncrypt(byte[] content, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] bytes = cipher.doFinal(content);
        return bytes;
    }
    /**
     * 私钥解密
     * @param content 待解密的内容
     * @param privateKey 私钥对象
     * @return 解密后的明文信息
     * @throws Exception
     */
    public static byte[] privateDecrypt(byte[] content, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] bytes = cipher.doFinal(content);
        return bytes;
    }

4、常用公钥密码算法

• 国际上常见的非对称加密算法有:RSA、ECC(移动设备用)、Diffie-Hellman(密钥交换、密钥协商使用)、El Gamal、DSA(数字签名用)。
• 随着《网络安全法》以及《等保2.0》,以及未来的《等保3.0》的发布,以及政策层面要求密码设备国产化要求,目前商用环境使用最多的是SM1算法(算法未公开,据说是军用算法??)和SM2算法,当然为了支持国际化,RSA2048、ECC相关曲线也有使用。
• 国密算法相关内容可参考:https://www.cnblogs.com/dhcn/p/12512124.html

如有理解不全或者理解有误的地方,欢迎大家批评指正!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值