openssl之数字证书签名,CA认证原理及详细操作

2024-09-04 11:18

本文主要是介绍openssl之数字证书签名,CA认证原理及详细操作,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://blog.sina.com.cn/s/blog_cfee55a70102wn3h.html

openssl之数字证书签名,CA认证原理及详细操作

  (2016-03-23 09:42:39)
转载
标签: 

rsa

 

ca认证

 

php签名

 

非对称加密技术

分类: 软件设计

1 公钥密码体系(Public-key Cryptography)

公钥密码体系,又称非对称密码体系。它使用二个密钥,一个用于加密信息,另一个用于解密信息。 这二个密钥间满足一定数学关系,以至用二个密钥中的任何一个加密的数据,只能用另外一个进行数据解密。每个用户拥有二个密钥,一个被称之为公钥,另一个被称之为私钥,并将公钥分发给其它用户。由于这二个密钥间的数学关系, 任何收到该用户公钥的其它用户可以保证发送用此公钥进行加密的数据只有该用户用自己的私钥才能进行解密。 当然此项保证是建立在用户私钥的私有性基础之上。目前最著名的公钥密码算法为RSA算法,它是由RivestShamirAdleman共同发明的。见图示:

openssl之数字证书签名,CA认证原理及详细操作

2      摘要算法

摘要算法是一种方法,它将一个任意长度的数据变换为一个定长的数据串,这一定长的数据串被称为消息摘要,也有数据指纹之称。合格的摘要算法必须满足下列条件:

找出具有相同摘要的消息集合在技术上是不可能的;

对一给定的消息摘要,反向计算出消息本身在技术上是不可行的。

数据发送方在数据发送前,首先用摘要算法对数据计算消息摘要,然后将数据和消息摘要一起发送给接受方。接受方用相同的摘要算法对数据重新计算消息摘要,通过对二个消息摘要的比较,可以明确地判断出数据在传输过程中是否被篡改。结果相同表示数据未被修改,而结果不同表明数据被修改或数据被丢失,从而保证数据在传输过程中的完整性。常用的摘要算法有MD2MD5,它是由RSA实验室发明的,具体算法请参阅RFC1319RFC1321 见图示:

openssl之数字证书签名,CA认证原理及详细操作

3      数字签名

数字签名实际上是非对称密码算法和消息摘要算法的一种组合应用,其目的在于:如某人张三对一段消息进行了数字签名,那么其它的人都能验证这个签名确实是张三签的,同时也能验证张三签名后数据是否被篡改。下面的例子将详细介绍Alice如何对一份合同M进行数字签名,同时Bob又是如何来验证她所签的合同。见图示:

数字签名示意图openssl之数字证书签名,CA认证原理及详细操作


Alice准备了一份合同M

Alice用摘要算法计算出该合同M的消息摘要MD

Alice用非对称算法和自己的私钥对合同消息摘要MD进行加密,该密文S就是合同的数字签名;

Alice将合同M和合同的数字签名S合并在一起,通过网络传送到合同的接受者Bob

Bob收到Alice的合同M及合同的数字签名S

BobAlice的公钥对合同签名S进行解密,得到Alice计算的合同摘要MD

Bob采用相同摘要算法对收到的合同重新计算消息摘要MD'

Bob比较MDMD'是否相等?

如结果相等,根据摘要算法的特性表明合同在传输过程中未被篡改。同时由于非对称加密算法的特性可以断定合同确实是Alice发送的,因为用Alice公钥能解密成功的数据只有Alice用她自己私钥对其进行加密才能产生,而她的私钥其它人是无法获取的。

为保证用户之间在网上传递信息的安全性、真实性、可靠性、完整性和不可抵赖性,不仅需要对用户的身份真实性进行验证,也需要有一个具有权威性、公正性、唯一性的机构,负责向电子商务的各个主体颁发并管理符合国内、国际安全电子交易协议标准的电子商务安全证,并负责管理所有参与网上交易的个体所需的数字证书,因此是安全电子交易的核心环节。所以需要向电子商务认证授权机构(CA, Certificate Authority)申请签发公钥证书。

4      数字签名私钥及公钥证书生成

以在windows平台生成为例:

第一步,下载openSSL工具,下载

第二步,打开 openssl 文件夹下的 bin 文件夹,执行 openssl.exe 文件;

第三步,生成 RSA 私钥,输入genrsa -out rsa_private_key.pem 1024,此时,我们可以在 bin 文件夹中看到一个文件名为rsa_private_key.pem 的文件,用 记事本打开它,可以看到-----BEGIN RSA PRIVATE KEY-----开头,-----END RSA PRIVATE KEY-----结尾的没有换行的字符串,这个就是原始的 RSA 私钥。(PHP签名需要原始私钥,JAVA需要对原始私钥做pkcs8转码后再去除开头和结尾)

第四步,创建证书请求。使用私钥生成一个证书请求,输入req -new -out cert.csr -key private.pem,这里我们会要求输入国家、组织、姓名等信息,但是不会要求输入证书有效天数,因为证书有效天数是CA认证中心给我们的;然后我们会把这个生成好的cert.csrCertificate Signing Request (CSR):证书签名申请)发给CA认证中心,证书请求提交到CA认证中心后会得到一份证书。

(测试时,根据cert.csr生成自签署根证书,暂时不通过CA认证中心自行进行证书签名,这里用是x509

openssl x509 -req -in cert.csr -out public.der -outform der -signkey private.pem -days 3650 //10年有效)

5      PHP版RSA签名代码示例

   
    function sign($data,$rsaPrivateKeyPem) {
    //读取私钥文件
    $priKey = file_get_contents($rsaPrivateKeyPem);
    //转换为openssl密钥,必须是没有经过pkcs8转换的私钥
    $res = openssl_get_privatekey($priKey);
    //调用openssl内置签名方法,生成签名$sign
    openssl_sign($data, $sign, $res);
    //释放资源
    openssl_free_key($res);
    //base64编码
    $sign = base64_encode($sign);
    return $sign;
    }

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.CertificateFactory;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Date;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import org.apache.commons.codec.binary.Base64;

public class RSASignatureService{
    private String algonrithm = "SHA1WithRSA";  
    private RSAPublicKey publicKey;  
    private RSAPrivateKey privateKey;  
  
    public RSASignatureService(){
   
    }
    
    public static void main(String[] args) throws FileNotFoundException, Exception {
    RSASignatureService ser = new RSASignatureService();
    ser.setPrivateKey(new FileInputStream("E:/private_key_pkcs8.pem"));
    String sign = ser.sign("哈哈");
//     System.out.println(sign);
//     ser.setPublicKey(new FileInputStream("E:/public_key.pem"));//设置公钥
    ser.setPublicDer(new FileInputStream("E:/public.der"));//设置公钥证书
     System.out.println(ser.verify(sign, "哈哈"));//验签
    String ecrypt = ser.encrpt("哈哈");//私钥加密
    String s = ecrypt;
    System.out.println(ser.decrypt(s));//公钥解密
}
    
 
    public String encrpt(String content) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{  
// 使用默认RSA
        Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] cipherData = cipher.doFinal(content.getBytes());
String signature=Base64.encodeBase64String(cipherData);
return signature;
    }  
    
   
    public String decrypt(String sign) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{
    // 使用默认RSA
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
byte[] output = cipher.doFinal(Base64.decodeBase64(sign));
return new String(output);
}
    
   
    public String sign(String content) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException{
    Signature signature = Signature.getInstance(algonrithm);
        signature.initSign(privateKey);
        signature.update( content.getBytes());
        byte[] signed = signature.sign();
        return Base64.encodeBase64String(signed);
    }
  
     
    public boolean verify(String sign, String content) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException{  
    Signature signature = Signature.getInstance(algonrithm);
    signature.initVerify(publicKey);
    signature.update(content.getBytes());
    boolean bverify = signature.verify(Base64.decodeBase64(sign));
    return bverify;
    }
    
     
    private static byte[] toByteArray(InputStream in) throws IOException {  
        FileChannel channel = null;  
        FileInputStream fs = null;  
        try {  
            fs = (FileInputStream) in;  
            
            channel = fs.getChannel();  
            ByteBuffer byteBuffer = ByteBuffer.allocate((int) channel.size());  
            while ((channel.read(byteBuffer)) > 0) {  
                // do nothing  
                // System.out.println("reading");  
            }  
            return byteBuffer.array();  
        } catch (IOException e) {  
            e.printStackTrace();  
            throw e;  
        } finally {  
            try {  
                channel.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
            try {  
                fs.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }
    
public void setPrivateKey(InputStream privateKeyResource) throws Exception {
byte[] tmp = toByteArray(privateKeyResource);
byte[] buffer = Base64.decodeBase64(new String(tmp));
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
privateKey = (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
}

public void setPublicKey(InputStream publicKeyResource) throws Exception {
byte[] tmp = toByteArray(publicKeyResource);
byte[] buffer = Base64.decodeBase64(tmp);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);
}
public void setPublicDer(InputStream publicKeyResource) throws Exception {
CertificateFactory of = CertificateFactory.getInstance("X.509");
java.security.cert.Certificate ceof = of.generateCertificate(publicKeyResource);
// 获取CA的公钥
publicKey = (RSAPublicKey) ceof.getPublicKey();
}
}


这篇关于openssl之数字证书签名,CA认证原理及详细操作的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1135872

相关文章

Python调用Orator ORM进行数据库操作

《Python调用OratorORM进行数据库操作》OratorORM是一个功能丰富且灵活的PythonORM库,旨在简化数据库操作,它支持多种数据库并提供了简洁且直观的API,下面我们就... 目录Orator ORM 主要特点安装使用示例总结Orator ORM 是一个功能丰富且灵活的 python O

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Spring AI集成DeepSeek的详细步骤

《SpringAI集成DeepSeek的详细步骤》DeepSeek作为一款卓越的国产AI模型,越来越多的公司考虑在自己的应用中集成,对于Java应用来说,我们可以借助SpringAI集成DeepSe... 目录DeepSeek 介绍Spring AI 是什么?1、环境准备2、构建项目2.1、pom依赖2.2

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

Goland debug失效详细解决步骤(合集)

《Golanddebug失效详细解决步骤(合集)》今天用Goland开发时,打断点,以debug方式运行,发现程序并没有断住,程序跳过了断点,直接运行结束,网上搜寻了大量文章,最后得以解决,特此在这... 目录Bug:Goland debug失效详细解决步骤【合集】情况一:Go或Goland架构不对情况二:

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应

Python itertools中accumulate函数用法及使用运用详细讲解

《Pythonitertools中accumulate函数用法及使用运用详细讲解》:本文主要介绍Python的itertools库中的accumulate函数,该函数可以计算累积和或通过指定函数... 目录1.1前言:1.2定义:1.3衍生用法:1.3Leetcode的实际运用:总结 1.1前言:本文将详

Deepseek R1模型本地化部署+API接口调用详细教程(释放AI生产力)

《DeepseekR1模型本地化部署+API接口调用详细教程(释放AI生产力)》本文介绍了本地部署DeepSeekR1模型和通过API调用将其集成到VSCode中的过程,作者详细步骤展示了如何下载和... 目录前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装oll

Spring Boot整合log4j2日志配置的详细教程

《SpringBoot整合log4j2日志配置的详细教程》:本文主要介绍SpringBoot项目中整合Log4j2日志框架的步骤和配置,包括常用日志框架的比较、配置参数介绍、Log4j2配置详解... 目录前言一、常用日志框架二、配置参数介绍1. 日志级别2. 输出形式3. 日志格式3.1 PatternL

Springboot 中使用Sentinel的详细步骤

《Springboot中使用Sentinel的详细步骤》文章介绍了如何在SpringBoot中使用Sentinel进行限流和熔断降级,首先添加依赖,配置Sentinel控制台地址,定义受保护的资源,... 目录步骤 1: 添加 Sentinel 依赖步骤 2: 配置 Sentinel步骤 3: 定义受保护的