Openssl实现双向认证教程(附服务端客户端代码)

OpenSSL实现双向认证教程

此教程将指导如何使用OpenSSL实现双向认证,包含服务端与客户端代码。在本教程中,我们将学习:

  • 什么是双向认证
  • 生成RSA密钥对
  • 生成自签名的根证书
  • 生成服务器证书请求(CSR)
  • 生成服务器证书
  • 配置服务端
  • 生成客户端证书请求(CSR)
  • 生成客户端证书
  • 配置客户端
  • 测试双向认证

什么是双向认证

在SSL/TLS连接中,通常只有服务器需要验证,因为它提供了服务(例如网站)给客户端。但是,在某些情况下,需要对客户端进行验证(例如API或者是移动设备上的应用程序)。这时就需要使用双向认证,确保只有经过认证的客户端可以访问服务器提供的服务。

生成RSA密钥对

首先,需要生成RSA密钥对。我们将使用OpenSSL生成2048位的RSA密钥对。以下命令可以生成密钥对:

openssl genrsa -out rootCA.key 2048

生成自签名的根证书

使用生成的RSA密钥对,可以生成自签名的根证书。以下命令可以生成根证书和私钥:

openssl req -x509 -new -key rootCA.key -days 3650 -out rootCA.crt

其中,-x509参数指定我们将要生成自签名证书,-new参数表示新建证书,-days参数指定证书的有效期天数,-out参数指定输出文件。执行完该命令后,将生成名为rootCA.crt的自签名根证书。

生成服务器证书请求(CSR)

使用以下命令生成服务器证书请求(CSR):

openssl req -new -key server.key -out server.csr

其中,-new参数表示新建证书请求,-key参数表示指定密钥文件,-out参数指定输出文件。执行完该命令后,将生成一个名为server.csr的证书请求文件。

生成服务器证书

使用以下命令生成服务器证书:

openssl x509 -req -in server.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out server.crt -days 3650

其中,-req参数表示该证书是从证书请求生成的,-in参数指定证书请求文件,-CA参数指定根证书,-CAkey指定RSA私钥,-CAcreateserial参数表示自动创建序列号,-out参数指定输出文件名,-days参数指定证书的有效期天数。执行完该命令后,会生成一个名为server.crt的服务器证书。

配置服务端

生成一个名为server.js的Node.js文件,将以下代码添加到文件中:

const fs = require('fs');
const https = require('https');
const express = require('express');

const app = express();

const options = {
    key: fs.readFileSync('server.key'),
    cert: fs.readFileSync('server.crt')
};

app.get('/', function(req, res) {
    res.send('Hello World!');
});

https.createServer(options, app).listen(8000, function() {
    console.log('Server started on port 8000.');
});

在代码运行之前,需要确保安装expresshttps模块。执行以下命令安装这两个依赖项:

npm install express https

要启动服务器,请运行以下命令:

node server.js

生成客户端证书请求(CSR)

使用以下命令生成客户端证书请求(CSR):

openssl req -new -key client.key -out client.csr

其中,-new参数表示新建证书请求,-key参数表示指定密钥文件,-out参数指定输出文件。执行完该命令后,将生成一个名为client.csr的证书请求文件。

生成客户端证书

使用以下命令生成客户端证书:

openssl x509 -req -in client.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out client.crt -days 3650

其中,-req参数表示该证书是从证书请求生成的,-in参数指定证书请求文件,-CA参数指定根证书,-CAkey指定RSA私钥,-CAcreateserial参数表示自动创建序列号,-out参数指定输出文件名,-days参数指定证书的有效期天数。执行完该命令后,会生成一个名为client.crt的客户端证书。

配置客户端

生成一个名为client.js的Node.js文件,将以下代码添加到文件中:

const fs = require('fs');
const https = require('https');

const options = {
    hostname: 'localhost',
    port: 8000,
    path: '/',
    method: 'GET',
    key: fs.readFileSync('client.key'),
    cert: fs.readFileSync('client.crt'),
    ca: fs.readFileSync('rootCA.crt')
};

https.request(options, function(res) {
    console.log('statusCode:', res.statusCode);
    console.log('headers:', res.headers);

    res.on('data', function(d) {
        process.stdout.write(d);
    });

}).end();

在运行代码之前,确保已经生成client.keyclient.crt文件。此外,还需要将rootCA.crt文件放置到运行代码的目录中。

要运行客户端,执行以下命令:

node client.js

测试双向认证

为了测试双向认证是否成功工作,您应该分别启动客户端和服务器,然后检查服务器的输出以查看是否成功。在终端运行以下两个命令:

$ node server.js
Server started on port 8000.

$ node client.js
Hello World!

如果您看到“Hello World!”的消息,则表明双向认证已成功工作!

示例

以下是使用双向认证的API服务器端和移动应用程序客户端的示例说明。

API服务器端

您可以使用此代码在API服务器端上实现双向认证。

const fs = require('fs');
const https = require('https');
const express = require('express');

const app = express();

const options = {
    key: fs.readFileSync('server.key'),
    cert: fs.readFileSync('server.crt'),
    requestCert: true,
    rejectUnauthorized: true,
    ca: [ fs.readFileSync('client.crt') ]
};

app.get('/', function(req, res) {
    res.send('Hello World!');
});

https.createServer(options, app).listen(8000, function() {
    console.log('Server started on port 8000.');
});

在客户端证书中指定完整的路径,而不是只指定文件名,例如:

ca: [ fs.readFileSync('/certs/client.crt') ]

移动应用程序客户端

您可以使用此代码在移动应用程序中实现双向认证。

try {
    // Create a KeyStore containing our trusted CA
    String keyStoreType = KeyStore.getDefaultType();
    KeyStore keyStore = KeyStore.getInstance(keyStoreType);
    keyStore.load(null, null);
    InputStream is = context.getAssets().open("rootCA.crt");
    CertificateFactory cf = CertificateFactory.getInstance("X.509");
    Certificate caCert = cf.generateCertificate(is);
    keyStore.setCertificateEntry("caCert", caCert);

    // Create a KeyStore containing our client certificate
    KeyStore clientKeyStore = KeyStore.getInstance("PKCS12");
    InputStream clientCert = context.getAssets().open("client.p12");
    clientKeyStore.load(clientCert, "client_password".toCharArray());

    // Create a TrustManager that trusts the CA in our KeyStore
    String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
    tmf.init(keyStore);

    // Create a KeyManager that uses our client certificate
    String kmfAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
    KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfAlgorithm);
    kmf.init(clientKeyStore, "client_password".toCharArray());

    // Create an SSLContext that uses our TrustManager and KeyManager
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

    // Create an HTTPS connection and send a request
    URL url = new URL("https://example.com/api");
    HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
    conn.setSSLSocketFactory(sslContext.getSocketFactory());
    conn.setRequestMethod("GET");
    conn.connect();

    // Read the response
    InputStream in = conn.getInputStream();
    int bytesRead;
    byte[] buffer = new byte[1024];
    while ((bytesRead = in.read(buffer)) != -1) {
        System.out.write(buffer, 0, bytesRead);
    }
    in.close();
} catch (Exception e) {
    e.printStackTrace();
}

在客户端证书中指定完整的路径,而不是只指定文件名,例如:

InputStream clientCert = context.getAssets().open("client.p12");

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Openssl实现双向认证教程(附服务端客户端代码) - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • microsoft+r:microsoftropen(mro)安装和多核运作

    Microsoft R Open (MRO) 是一个开源的 R 语言发行版,由 Microsoft 提供支持。它包含了 R 语言的核心组件以及一些常用的 R 包,同时还提供了一些优化和强功能,如多核并行计算和大数据处理等。本文将介绍如何安装和配置 Microsoft R Open,并使用多核并行计算功能。 步骤一:下载和安装 Microsoft R Open…

    other 2023年5月8日
    00
  • Java中StringBuilder与StringBuffer使用及源码解读

    Java中StringBuilder与StringBuffer使用及源码解读 StringBuilder与StringBuffer的概述 StringBuilder与StringBuffer是Java中两个非常常用的字符串拼接工具,在处理大量字符串拼接时,它们相比于String的”+”连接符表现更加出色。 这两个类都继承自AbstractStringBuil…

    other 2023年6月27日
    00
  • 关于java入门与java开发环境配置详细教程

    关于Java入门 本教程将指导您如何入门Java编程。Java是一门跨平台的编程语言,在Web开发、桌面开发以及移动开发领域都有广泛应用。本教程包括Java基础语法、常用类库以及一些基本的编程思想,帮助您在开始Java编程之前对它有一个初步了解。 Java入门基础 Java入门基础包括以下内容: Java基础语法 类、对象和方法 控制语句和循环结构 面向对象…

    other 2023年6月27日
    00
  • Android打造属于自己的新闻平台(客户端+服务器)

    Android打造属于自己的新闻平台(客户端+服务器)攻略 1. 客户端的构建 1.1 开发工具的选择 首先选取Android Studio作为客户端的开发工具,Android Studio是Google推出的一款集成开发环境(IDE),为用户提供丰富的开发工具和便捷的操作方式。 1.2 技术栈的选择 在选择技术栈时,可根据项目需求和开发人员经验进行选择。常…

    other 2023年6月25日
    00
  • 在Linux桌面上随意使用Windows文档的方法

    在Linux桌面上使用Windows文档的方法有很多种,下面提供两种常用的方法: 方法一:安装WPS Office 首先,在Linux操作系统的应用商店中搜索WPS Office,下载并安装该软件。 安装完成后,在桌面上找到WPS Office应用图标,打开软件。 在WPS Office中,选择“文件”→“打开”,浏览到Windows文档所在的位置,选择需要…

    other 2023年6月27日
    00
  • 微信网页授权并获取用户信息的方法

    微信网页授权是指开发者在微信内网页获取用户基本信息的授权过程。通过微信网页授权,用户在进入网页时,如果用户同意授权,即可获取其基本信息,包括:头像、名称、性别等信息。下面我们来详细讲解“微信网页授权并获取用户信息的方法”。 步骤一:申请开发者ID和App Secret 在开始使用微信网页授权功能之前,需要先在微信公众平台上申请开发者ID和App Secret…

    other 2023年6月26日
    00
  • Excel鲜为人知的二十五个技巧

    Excel鲜为人知的二十五个技巧攻略 Excel是一款功能强大的电子表格软件,但是其中有一些鲜为人知的技巧可以帮助用户更高效地使用它。本攻略将详细介绍Excel鲜为人知的二十五个技巧,并提供两个示例说明。 技巧一:使用快捷键 快捷键可以大大提高Excel的使用效率。以下是一些常用的快捷键: Ctrl + C:复制选定的单元格或区域。 Ctrl + V:粘贴复…

    other 2023年8月18日
    00
  • 关于sourcetree:sourcetree-mercurial-身份验证

    关于Sourcetree-Mercurial身份验证:Sourcetree-Mercurial身份验证攻略 Sourcetree是一款免费的Git和Mercurial客户端,可以帮助开发者更方便地管理代码。在使用Sourcetree时,有时会遇到Mercurial身份验证的问题。本攻略将介绍如何解决Sourcetree-Mercurial身份验证问题。 步骤…

    other 2023年5月9日
    00
合作推广
合作推广
分享本页
返回顶部