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日

相关文章

  • 如何安装vue-cli-service

    以下是安装vue-cli-service的完整攻略,包括两个示例说明。 步骤 以下是安装vue-cli-service的基本步骤: 安装Node.js和npm。 在安装vue-cli-service之前,需要先安装Node.js和npm。从Node.js官网下载安装包,然后按照安装向导进行安装。 安装 Vue CLI。 在命令行中运行以下命令来安装Vue C…

    other 2023年5月6日
    00
  • C语言行优先和列优先的问题深入分析

    C语言行优先和列优先的问题深入分析 什么是行优先和列优先 行优先和列优先是对于二维数组进行访问时的两种不同方式。在C语言中,二维数组是按照行优先存储的。这意味着在二维数组中,连续的内存单元是按照行顺序存储的,也就是说,第一行的元素先于第二行。 列优先存储方式与之相反,它是按照列顺序来存储数组元素的,也就是说,一个列中的元素先于下一列中的元素。 为什么要使用行…

    other 2023年6月26日
    00
  • 提升Python效率之使用循环机制代替递归函数

    当我们需要重复执行某一段代码时,我们有两种主要的编程机制选择:循环和递归。两种方式都可以用来实现深度优先遍历、迭代等常见操作,但在Python中循环的效率更高。本文将介绍如何使用循环机制代替递归函数,提升Python代码的效率。 什么是递归? 递归是一种函数调用自身的技术。在Python中,递归函数可以很方便地解决许多问题,如计算阶乘、斐波那契数列等。但递归…

    other 2023年6月27日
    00
  • Android实现右边抽屉Drawerlayout效果

    Android实现右边抽屉Drawerlayout效果攻略 在Android中,可以使用DrawerLayout来实现抽屉效果,包括左边抽屉和右边抽屉。下面是实现右边抽屉DrawerLayout效果的完整攻略。 步骤一:添加依赖库 首先,在项目的build.gradle文件中添加DrawerLayout的依赖库。在dependencies块中添加以下代码: …

    other 2023年9月7日
    00
  • WP8.1开发者预览版怎么样?你必须了解的几件事

    首先我们来看一下WP8.1开发者预览版的几个需要注意的事项: 1. 它是测试版,而不是稳定版 WP8.1开发者预览版是提供给WP开发者测试和验证他们的应用程序的版本。它并不是最终发布的稳定版,因此你需要注意它可能存在一些问题和Bug。 2. 安装之前备份数据 在安装WP8.1开发者预览版之前,你需要备份你的数据,包括联系人、短信、照片、视频等等,以防数据丢失…

    other 2023年6月26日
    00
  • DOS命令行下使用HaoZip进行文件压缩的方法

    以下是在DOS命令行下使用HaoZip进行文件压缩的步骤: 1. 下载和安装HaoZip 首先需要下载并安装HaoZip压缩软件,并将其添加到系统环境变量中,以便在命令行中使用。安装过程中选中“将HaoZip添加到系统环境变量中”选项即可。 2. 使用HaoZip压缩文件 在DOS命令行下,使用hz.exe命令来执行HaoZip。以下是两个基本示例: 压缩某…

    other 2023年6月26日
    00
  • word怎么设置小型大写字母small capitals?

    要在Word中设置小型大写字母(small capitals),请按照以下步骤进行操作: 首先,打开Word文档并选择要应用小型大写字母的文本。 在顶部菜单栏中,找到并点击“字体”选项卡。 在弹出的字体对话框中,您将看到一个名为“字体效果”的下拉菜单。点击该下拉菜单。 在下拉菜单中,您将看到一个选项称为“小型大写字母”(Small Capitals)。选择该…

    other 2023年8月16日
    00
  • Android中Spinner控件之键值对用法实例分析

    Android中Spinner控件之键值对用法实例分析 Spinner是Android中常用的下拉选择控件,可以用于展示一组选项供用户选择。在Spinner中,我们可以使用键值对的方式来设置选项的显示文本和对应的值。下面是一个详细的攻略,包含了使用键值对的示例说明。 步骤一:在布局文件中定义Spinner控件 首先,在布局文件中定义Spinner控件。以下是…

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