在前面关于加密的文章中,讲到使用open62541自带的python脚本create_self-signed.py去生成证书和私匙,该脚本运行需要安装库netifaces
pip3 install netifaces
在Linux下可以正确安装和使用。但是在Windows上却没那么顺利,该库依赖cl.exe,这个需要安装VS或者单独安装VS的编译器,而且python的版本还要和对应编译器版本匹配… 有点麻烦
一 解决办法
经过研究,这个库主要用来自动获取当前PC的IP地址,也可以在命令行使用ipconfig来查看,效果一样。
本人对这个脚本进行了一定修改,增加一个-a选项,来指定当前PC的地址,然后把脚本中使用netifaces的地方都注释掉,这样就可以不用安装netifaces了
修改后的脚本命名为create_self-signed_modify.py,如下,
#!/usr/bin/env python
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# Copyright 2019 (c) Kalycito Infotech Private Limited
#
# import netifaces
import sys
import os
import socket
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('outdir',
type=str,
nargs='?',
default=os.getcwd(),
metavar='<OutputDirectory>')
parser.add_argument('-u', '--uri',
metavar="<ApplicationUri>",
type=str,
default="",
dest="uri")
parser.add_argument('-k', '--keysize',
metavar="<KeySize>",
type=int,
dest="keysize")
parser.add_argument('-c', '--certificatename',
metavar="<CertificateName>",
type=str,
default="",
dest="certificatename")
parser.add_argument('-a',
metavar="<LocalIPAddr>",
type=str,
nargs='+',
default="",
dest="localipaddr")
args = parser.parse_args()
if not os.path.exists(args.outdir):
sys.exit('ERROR: Directory %s was not found!' % args.outdir)
keysize = 2048
if args.keysize:
keysize = args.keysize
if args.uri == "":
args.uri = "urn:open62541.server.application"
print("No ApplicationUri given for the certificate. Setting to %s" % args.uri)
os.environ['URI1'] = args.uri
if args.certificatename == "":
certificatename = "server"
print("No Certificate name provided. Setting to %s" % certificatename)
if args.certificatename:
certificatename = args.certificatename
certsdir = os.path.dirname(os.path.abspath(__file__))
# # Function return TRUE (1) when an IP address is associated with the
# # given interface
# def is_interface_up(interface):
# addr = netifaces.ifaddresses(interface)
# return netifaces.AF_INET in addr
# # Initialize looping variables
# interfaceNum = 0
# iteratorValue = 0
# # Read the number of interfaces available
# numberOfInterfaces = int(format(len(netifaces.interfaces())))
# # Traverse through the available network interfaces and store the
# # corresponding IP addresses of the network interface in a variable
# for interfaceNum in range(0, numberOfInterfaces):
# # Function call which returns whether the given
# # interface is up or not
# check = is_interface_up(netifaces.interfaces()[interfaceNum])
# # Check if the interface is up and not the loopback one
# # If yes set the IP Address for the environmental variables
# if check != 0 and netifaces.interfaces()[interfaceNum] != 'lo':
# if iteratorValue == 0:
# os.environ['IPADDRESS1'] = netifaces.ifaddresses(netifaces.interfaces()[interfaceNum])[netifaces.AF_INET][0]['addr']
# if iteratorValue == 1:
# os.environ['IPADDRESS2'] = netifaces.ifaddresses(netifaces.interfaces()[interfaceNum])[netifaces.AF_INET][0]['addr']
# iteratorValue = iteratorValue + 1
# if iteratorValue == 2:
# break
# # If there is only one interface available then set the second
# # IP address as loopback IP
# if iteratorValue < 2:
# os.environ['IPADDRESS2'] = "127.0.0.1"
if len(args.localipaddr) == 1:
os.environ['IPADDRESS1'] = args.localipaddr[0]
os.environ['IPADDRESS2'] = "127.0.0.1"
elif len(args.localipaddr) >= 2:
os.environ['IPADDRESS1'] = args.localipaddr[0]
os.environ['IPADDRESS2'] = args.localipaddr[1]
else:
sys.exit(0)
# os.environ['IPADDRESS1'] = args.localipaddr
# os.environ['IPADDRESS2'] = "127.0.0.1"
os.environ['HOSTNAME'] = socket.gethostname()
openssl_conf = os.path.join(certsdir, "localhost.cnf")
os.chdir(os.path.abspath(args.outdir))
os.system("""openssl req \
-config {} \
-new \
-nodes \
-x509 -sha256 \
-newkey rsa:{} \
-keyout localhost.key -days 365 \
-subj "/C=DE/O=open62541/CN=open62541Server@localhost"\
-out localhost.crt""".format(openssl_conf, keysize))
os.system("openssl x509 -in localhost.crt -outform der -out %s_cert.der" % (certificatename))
os.system("openssl rsa -inform PEM -in localhost.key -outform DER -out %s_key.der"% (certificatename))
os.remove("localhost.key")
os.remove("localhost.crt")
print("Certificates generated in " + args.outdir)
可以使用如下命令去查看帮助信息,
python create_self-signed_modify.py -h
二 使用
把这个脚本放在tools/certs目录下,和localhost.cnf在同一目录,
PS:需要事先在Windows下安装openssl,可以自行网上搜索,安装完毕后要保证在dos下识别openssl命令。
然后打开dos,cd到该目录下,先使用ipconfig去查看本机ip地址,假如查得地址是192.168.1.133
最后执行如下命令,
python create_self-signed_modify.py . -a 192.168.1.133
这样就可以生成证书和私匙了,如下,
如果本机有多个网络地址,可以这样使用,
python create_self-signed_modify.py . -a 192.168.1.133 192.168.1.122
但是最多只能添加2个地址到证书里。注意,如果要指定证书的URI,还需要使用-u参数。
生成完毕后,可以使用以下命令去查看证书里的ip地址以及URI,
# 查看Client证书
openssl x509 -in server_cert.der -inform der -noout -text