java密码学-数字证书(超详细)

简介: 消息摘要算法用于验证数据完整性服务,对称加密算法和非对称加密算法用于保证数据保密性服务,数字签名算法用于抗否认服务。数字证书集合了多种密码学算法:自身带有公钥信息,可完成相应的加密/解密操作,同时,还带有数字签名,可鉴别消息来源;且自身带有消息摘要信息,可验证证书的完整性;由于证书本身含有用户身份信息,因而具有认证性。数字证书有多种文件编码格式,主要包含CER编码(变长模式)、DER编码(定长模式)和PKCS系列等

一、前言



消息摘要算法用于验证数据完整性服务,对称加密算法和非对称加密算法用于保证数据保密性服务,数字签名算法用于抗否认服务。


数字证书集合了多种密码学算法:自身带有公钥信息,可完成相应的加密/解密操作,同时,还带有数字签名,可鉴别消息来源;且自身带有消息摘要信息,可验证证书的完整性;由于证书本身含有用户身份信息,因而具有认证性。


数字证书有多种文件编码格式,主要包含CER编码(变长模式)、DER编码(定长模式)和PKCS系列等


二、数字证书的颁发



  1. 由数字证书需求方产生自己的密钥对
  2. 由数字证书需求方将算法、公钥和证书申请者身份信息传送给认证机构
  3. 由认证机构核实用户的身份,执行必要的步骤,确保请求确实由用户发送而来
  4. 由认证机构将数字证书颁发给用户 这里的认证机构如果是证书申请者本身,将获得自签名证书


三、加密交互



  1. 由客户端使用公钥对数据加密
  2. 由客户端向服务端发送加密数据
  3. 由服务器端使用私钥对数据解密


四、keytool--证书生成工具



环境变量的配置: 将keytool.exe所在目录添加到path下,然后就可以全局访问keytool命令


命令:
 -certreq            生成证书请求
 -changealias        更改条目的别名
 -delete             删除条目
 -exportcert         导出证书
 -genkeypair         生成密钥对
 -genseckey          生成密钥
 -gencert            根据证书请求生成证书
 -importcert         导入证书或证书链
 -importpass         导入口令
 -importkeystore     从其他密钥库导入一个或所有条目
 -keypasswd          更改条目的密钥口令
 -list               列出密钥库中的条目
 -printcert          打印证书内容
 -printcertreq       打印证书请求的内容
 -printcrl           打印 CRL 文件的内容
 -storepasswd        更改密钥库的存储口令
 //如果不知道命令的用法或者想知道这些命令下有哪些参数,可以使用一下命令
 keytool -command_name -help
 //比如keytool certreq -help
选项:
 -alias <alias>                  要处理的条目的别名
 -sigalg <sigalg>                签名算法名称
 -file <filename>                输出文件名
 -keypass <arg>                  密钥口令
 -keystore <keystore>            密钥库名称
 -dname <dname>                  唯一判别名
 -storepass <arg>                密钥库口令
 -storetype <storetype>          密钥库类型
 -providername <providername>    提供方名称
 -providerclass <providerclass>  提供方类名
 -providerarg <arg>              提供方参数
 -providerpath <pathlist>        提供方类路径
 -v                              详细输出
 -protected                      通过受保护的机制的口令


五、生成本地的证书和keystore



  • 生成本地证书
keytool -genkeypair -keyalg RSA -keysize 2048 -sigalg SHAwithRSA -validity 3600 -alias www.zlex.org -keystore zlex.keystore -dname "CN=www.zlex,org,OU=zlex,O=zlex,L=zlex,L=BJ,ST=BJ,C=CN"


  • 导出数字证书
keytool -exportcert -alias www.zlex.org -keystore zlex.keystore -file zlex.cer -rfc


  • 打印证书
keytool -printcert -file zlex.cer


  • 导出数字证书签发申请
keytool -certreq -alias www.zlex.org -keystore zlex.keystore -file zlex.csr -v


六、证书的使用



import javax.crypto.Cipher;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
public class CertCoder {
    //证书类型x509
    public static final String CERT_TYPE = "x.509";
    /**
     * 由keyStore获得私钥
     * @param keyStorePath 密钥库路径
     * @param alias 别名
     * @param pwd 密码
     * @return 私钥
     * @throws Exception
     */
    private static PrivateKey getPrivateKeyByKeyStore(String keyStorePath,String alias,String pwd) throws Exception {
        //获取密钥库
        KeyStore ks = getKeyStore(keyStorePath,pwd);
        //获得私钥
        return (PrivateKey)ks.getKey(alias,pwd.toCharArray());
    }
    /**
     * 由证书获得公钥
     * @param certPath 证书路径
     * @return 公钥
     * @throws Exception
     */
    private static PublicKey getPublicKeyByKeyStore(String certPath) throws Exception {
        //获得证书
        Certificate certificate = getCertificate(certPath);
        //获得公钥
        return  certificate.getPublicKey();
    }
    /**
     * 获得证书
     * @param certPath 证书路径
     * @return 证书
     */
    private static Certificate getCertificate(String certPath) throws Exception {
        //实例化证书工厂
        CertificateFactory factory = CertificateFactory.getInstance(CERT_TYPE);
        //获取证书文件流
        FileInputStream fis = new FileInputStream(certPath);
        //生成证书
        Certificate certificate = factory.generateCertificate(fis);
        //关闭文件流
        fis.close();
        return certificate;
    }
    /**
     * 获得证书
     * @param keyStorePath 密钥库路径
     * @param alias 别名
     * @param password 密码
     * @return 证书
     * @throws Exception
     */
    private static Certificate getCertificate(String keyStorePath,String alias,String password) throws Exception {
        //获得密钥库
        KeyStore keyStore = getKeyStore(keyStorePath,password);
        //获得证书
        return keyStore.getCertificate(alias);
    }
    /**
     * 获取KeyStore
     * @param keyStorePath 路径
     * @param pwd 密码
     * @return KeyStore
     * @throws Exception
     */
    private static KeyStore getKeyStore(String keyStorePath, String pwd) throws Exception {
        //实例化密钥库
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        //获得密钥库文件流
        FileInputStream is = new FileInputStream(keyStorePath);
        //加载密钥库
        keyStore.load(is,pwd.toCharArray());
        //关闭文件流
        is.close();
        return keyStore;
    }
    /**
     * 私钥加密
     * @param data 待加密数据
     * @param keyStorePath 密钥库路径
     * @param alias 别名
     * @param pwd 密码
     * @return 加密数据
     * @throws Exception
     */
    public static byte[] encryptByPrivateKey(byte[] data,String keyStorePath,String alias,String pwd) throws Exception {
        //获取私钥
        PrivateKey privateKey = getPrivateKeyByKeyStore(keyStorePath,alias,pwd);
        //对数据加密
        Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE,privateKey);
        return cipher.doFinal(data);
    }
    /**
     * 私钥解密
     * @param data 待解密数据
     * @param keyStorePath 密钥库路径
     * @param alias 别名
     * @param pwd 密码
     * @return 解密后的数据
     * @throws Exception
     */
    public static byte[] decryptByPrivateKey(byte[] data,String keyStorePath,String alias,String pwd) throws Exception {
        //获取私钥
        PrivateKey privateKey = getPrivateKeyByKeyStore(keyStorePath,alias,pwd);
        //解密操作
        Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE,privateKey);
        return cipher.doFinal(data);
    }
    /**
     * 公钥加密
     * @param data 代加密数据
     * @param certPath 证书路径
     * @return 密文
     * @throws Exception
     */
    public static byte[] encryptByPublicKey(byte[] data,String certPath) throws Exception {
        PublicKey publicKey = getPublicKeyByKeyStore(certPath);
        Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE,publicKey);
        return cipher.doFinal(data);
    }
    /**
     * 公钥解密
     * @param data 待解密数据
     * @param cerPath 证书路径
     * @return 明文
     * @throws Exception
     */
    public static byte[] decryptByOublicKey(byte[] data,String cerPath) throws Exception {
        PublicKey publicKey = getPublicKeyByKeyStore(cerPath);
        Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE,publicKey);
        return cipher.doFinal(data);
    }
    /**
     * 由证书构建签名
     * @param sign 待签名数据
     * @param keyStorePath 密钥库路径
     * @param alias 别名
     * @param pwd 密码
     * @return
     * @throws Exception
     */
    public static byte[] sign(byte[] sign,String keyStorePath,String alias,String pwd) throws Exception {
        //获取证书
        X509Certificate certificate = (X509Certificate) getCertificate(keyStorePath,alias,pwd);
        //构建签名
        Signature signature = Signature.getInstance(certificate.getSigAlgName());
        //获取私钥
        PrivateKey privateKey = getPrivateKeyByKeyStore(keyStorePath,alias,pwd);
        //初始化签名,有私钥构建
        signature.initSign(privateKey);
        signature.update(sign);
        return signature.sign();
    }
    /**
     * 认证
     * @param data 数据
     * @param sign 签名
     * @param cerPath 证书路径
     * @return 数据是否有改变
     * @throws Exception
     */
    public static boolean vertify(byte[] data,byte[] sign,String cerPath) throws Exception {
        //获取证书
        X509Certificate certificate = (X509Certificate) getCertificate(cerPath);
        //获取公钥
        PublicKey publicKey = certificate.getPublicKey();
        Signature signature = Signature.getInstance(certificate.getSigAlgName());
        signature.initVerify(publicKey);
        signature.update(data);
        return signature.verify(sign);
    }
    public static void main(String[] args) throws Exception {
        String pwd = "Lu3jianL6";
        String alias = "www.zlex.org";
        String cerPath = "D:\\Program Files\\Java\\jdk1.8.0_201\\bin\\zlex.cer";
        String keyStorePath = "D:\\Program Files\\Java\\jdk1.8.0_201\\bin\\zlex.keystore";
        byte[] data = "心里有思念的人就不会孤独".getBytes("utf-8");
        System.err.println("公钥加密,私钥解密");
        byte[] bytes = encryptByPublicKey(data, cerPath);
        System.out.println("公钥加密:" + new String(bytes,"utf-8"));
        byte[] result = decryptByPrivateKey(bytes, keyStorePath, alias, pwd);
        System.out.println("私钥解密:"+new String(result,"utf-8"));
        System.err.println("私钥加密,公钥解密");
        byte[] result1 = encryptByPrivateKey(data, keyStorePath, alias, pwd);
        System.out.println("私钥加密:" + new String(result1,"utf-8"));
        byte[] bytes1 = decryptByOublicKey(result1, cerPath);
        System.out.println("公钥解密:" + new String(bytes1,"utf-8"));
        System.err.println("数字签名");
        byte[] sign = sign(data,keyStorePath,alias,pwd);
        System.out.println("签名:" + new String(sign,"utf-8"));
        System.out.println(vertify(data,sign,cerPath));
    }
}
//执行结果
公钥加密,私钥解密
???H[:A??D`U???J?*??..7?S??D?v8??O????D?*????x? o? "H*#H??`T?v???\rf???a?H??*a?Av?c?0'?MN?PQ?O???1.VR?at:hV?zY?==?/?ī,???????`???$(?^?s 7/??2?'??5??Tu0??Js|9K*E%?A??C?ea?29 ?{?SM????^ ????????lf)???+???k??I?$?8?
私钥加密,公钥解密
私钥解密:心里有思念的人就不会孤独
私钥加密:u?)???  -l?x?n???EQ?N/??*????x?9?\w?i}ZZ??K??v?k???????$??j?z?h?/f`???8L?$<s#??<??8se?ы ē?*J???R??^??IZz{????A??2I4???%? P????????!?o??XjRBryMj?Z?X w& ?h???R?????WR???>>??.\G?q????a?A??$???# %????????v??L`)?????
公钥解密:心里有思念的人就不会孤独
数字签名
签名:^???<C??WqN:A[?WM?t??+?RP?X??7?_<???Z?R,?i8%qЬa??!?>G-6U??|??6?1r9|??hQ????h? z?5???O* H9??N
v?F2~s6I???DX??R^?@)A?NY/g?*??oQU?I@w=?? ??hDv? h-?????lO???#?O?3?`?c?P??X?u5TaO??Cz4??p?1???@6KS???5?!< y<?34?x$?R3n?G
true


七、应用场景



主要应用于电子商务活动和电子政务活动

目录
相关文章
|
3月前
|
存储 安全 Java
【网络安全】网络防护之旅 - Java安全机制探秘与数字证书引爆网络防线
【网络安全】网络防护之旅 - Java安全机制探秘与数字证书引爆网络防线
58 1
|
存储 算法 Java
java密码学-非对称加密算法
非对称加密算法与对称加密算法的主要区别在于非对称加密算法用于加密和解密的密钥不同,一个公开,称为公钥;一个保密,称为私钥。因此,非对称密码算法也称为双钥和公钥加密算法。 非对称加密算法解决了对称加密算法密钥分配问题,并极大的提高了算法的安全性。多种B2C或B2B应用均使用非对称加密算法作为数据加密的核心算法。解决了对称加密算法的密钥存储问题。
78 0
|
算法 搜索推荐 安全
java密码学-对称加密算法
java密码学-对称加密算法
75 0
|
Java
java密码学-数字签名
java密码学-数字签名
63 0
|
安全 算法 Java
【Java小工匠聊密码学】--消息摘要--SHA3算法
1、SHA3概述 1.1 SHA3简介 由于近年来对传统常用Hash 函数如MD4、MD5、SHA0、SHA1、RIPENMD 等的成功攻击,美国国家标准技术研究所(NIST)在2005年、2006年分别举行了2届密码Hash 研讨会;同时于2007年正式宣布在全球范围内征集新的下一代密码Hash算法,举行SHA-3竞赛·新的Hash算法将被称为SHA-3,并且作为新的安全Hash标准,增强现有的FIPS 180-2标准。
4927 0
|
Java 区块链
【Java小工匠聊密码学】--base58编码
1、Base58编码概述 1.1 什么是Base58编码? Base58是比特币的一种特殊编码方式,主要用于产生比特币钱包地址。相比Base64,Base58不使用数字"0",字母大写"O",字母大写"I",和字母小写"l",以及"+"和"/"符号。
3209 0
|
算法 Java 区块链
【Java小工匠聊密码学】--消息摘要--RIPEMD算法
1、什么是RIPEMD RIPEMD(RACE Integrity Primitives Evaluation Message Digest,RACE原始完整性校验消息摘要,是Hans Dobbertin等3人在md4,md5的基础上,于1996年提出来的。
1824 0
|
算法 Java 数据安全/隐私保护
【Java小工匠聊密码学】--非对称加密--RSA
1、什么是RSA 算法   RSA加密算法是一种非对称加密算法。在公开密钥加密和电子商业中RSA被广泛使用。RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。
1405 0
|
算法 Java 关系型数据库
【Java小工匠聊密码学】--非对称加密--DH密钥交换算法
1、DH密钥交换概述 Diffie-Hellman由Whitfield Diffie和Martin Hellman在1976年公布的一种密钥一致性算法。Diffie-Hellman是一种建立密钥的方法,而不是加密方法。
1662 0
|
算法 安全 Java
【Java小工匠聊密码学】--消息摘要--SHA算法
1、什么是SHA算法   安全散列算法(英语:Secure Hash Algorithm,缩写为SHA)是一个密码散列函数家族,是联邦信息处理标准(Federal Information Processing Standards,FIPS)所认证的安全散列算法。
1448 0