我来更新啦~之前的内容作废,我重新整理了以下,并且后续会持续更新~
1、简介
事实上,完全按照ocpp的安全部分来讲,是十分复杂的一个过程。ocpp协议的安全目标为以下四点:
-
允许在 CSMS 和充电站之间建立安全通信通道,该信道上信息的完整性和保密性应受到强大加密措施的保护。
-
在充电站和 CSMS 之间提供相互验证,双方都应能识别通信对象。
-
允许充电站检查固件映像的来源和完整性,并允许对这些映像进行不可抵赖性处理,从而提供安全的固件更新过程。
-
允许记录安全事件,以便监控智能充电系统的安全。与安全相关的事件及其 "关键性 "列表见附
OCPP2.0.1协议在设计的时候,并不是重新规定关于安全有关的内容,而是尽可能使用标准的网络技术,这样可以让使用OCPP协议的充电站(桩)开发者/平台运营商可以利用现有的网络库和软件进行经济有效的实现,所以OCPP的安全部份是基于TLS和X.509证书的公钥加密技术。
由于一般来说,云平台充当服务器,所以OCPP标准未对充电站实施不同用户或基于角色的访问控制,而建议在云平台上实施访问控制。
有关TLS和X.509的有关内容,在后续进行实际性尝试的时候,我会尽量简单明了的进行介绍。
OCPP 2.0.1 支持三种安全配置文件:下表显示了哪种配置文件使用哪种安全措施:
一般来说,第一种配置文件:使用基本身份验证的不安全传输 是不被推荐的,除非充电站和云平台是在一个非常安全且稳定的网络链接中进行的(VPN专用信道,可不是魔法那种VPN哦)。
所以,提到基本身份验证,我就要简单讲讲
基本身份验证:在这种情况下,客户端会向服务器发送用户名和密码。服务器会检查这些凭据是否有效,然后决定是否接受连接。这种方法的安全性取决于密码的复杂性和安全性
所以,如果说没有安全的网络信道的情况下,更建议使用3.带客户端证书的TLS进行加密链接。服务端和客户端会采用同一个可信的证书颁发机构签发的客户端/服务端证书,可以通过openssl进行具体验证客户端的公钥以及身份,主要是可以有效地拦截中间人的攻击,因为他只要没有证书颁发机构的根证书(ca)和相应的私钥(key),就没办法伪造一个有效的证书,对云平台发起攻击。
综上所述,对于充电站来说,更加要注意的是客户端证书的管理和维护,要根据平台的要求定期更新新的证书,并且通过云平台为中间人签发可信且有效的客户端证书。
注:协议中让我们注意的一点是,当充电站没有设置正确的日期和时间时,就无法验证服务器证书。解决这一问题的办法可以是使用 NTP、移动网络自动设置时间,或者使用安装工具在首次连接 前设置时间。虽然ocpp的心跳请求会请求一个当前的服务器时间,但是如果充电站本身没有经过一个基础的ntp校时的情况下,是无法与云平台建立有效的链接的。
2.安全配置文件要求
由于以上的介绍,我们只介绍一个最难的安全配置文件:带客户端证书的 TLS 配置文件
2.1 带客户端证书的 TLS 配置文件
(摘自ocpp2.0.1)
整个流程看起来其实一目了然,就是双方通过TLS证书进行双向认证,我们在看OCPP协议进行开发或学习时应该更加关注的是流程下方的Requirements,这个或许才是最麻烦且最经典的。
需求上,我尽量进行逐条分析或多条综合分析,并且给出相应的伪代码建议。
2.1.1 A00.FR.401、A00.FR.402:
The Charging Station SHALL authenticate itself to the CSMS using the Charging Station certificate.
The Charging Station certificate SHALL be used as a TLS client side certificate
充电站应使用充电站证书向 CSMS (云平台,后续会统一以CSMS代替云平台)进行身份验证,充电站证书必须用作 TLS 客户端证书
按照协议的描述来看,我们应该使用ca根证书和客户端的私钥生成一个客户端证书,在充电机出厂前,这个根证书应该已经在内存中写好了的,首次上电的时候,应该运行生成客户端证书的程序,我们采用openssl库即可(linux环境)
在这之前,我们先弄一个自签名的根证书出来,由于我没钱买一个正经可靠组织签发的CA证书,所以为了测试还是做一个自签名就可以了。
1、制作自签名证书
制作自签名证书其实比较简单,在你的linux环境采用以下命令就可以,我使用的是24.04,别问为啥,就是喜欢新的玩玩~
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out ca_key.pem
-
genpkey
为了生成密钥 -
-algorithm RSA
为了指定密钥的算法 -
-pkeyopt rsa_keygen_bits:3072
为了生成3072位的密钥,一般来说2048其实就已经足够用,已经相当安全了 -
-out ca_key.pem
: 这个参数指定了私钥的输出文件名
2、使用自签名证书生成RSA(证书签名请求)
openssl req -new -key ca_key.pem -out ca_cert.csr -subj "/CN=be001a.online"
-
req
: 这是OpenSSL的一个子命令,用来处理证书请求。它可以生成新的证书请求,也可以处理已有的证书请求。 -
-new
: 这个选项告诉OpenSSL生成一个新的证书请求。 -
-key ca_key.pem
: 这个选项指定了用来生成证书请求的私钥文件。在这个例子中,私钥文件的名称是ca_key.pem
。 -
-out ca_cert.csr
: 这个选项指定了生成的证书请求的输出文件。在这个例子中,输出文件的名称是ca_cert.csr
。 -
-subj "/CN=be001a.online"
: 这个选项指定了证书请求的主题。主题是一个包含了多个字段的字符串,用来描述证书的所有者。在这个例子中,主题只包含了一个字段,即通用名(CN,Common Name),其值为be001a.online
3、使用RSA和私钥生成自签名CA根证书
openssl x509 -req -in ca_cert.csr -signkey ca_key.pem -out ca_cert.pem -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1
-
x509
: 这是OpenSSL的一个子命令,用来处理X.509证书。它可以生成新的证书,也可以处理已有的证书。 -
-req
: 这个选项告诉OpenSSL这是一个基于证书请求的操作。 -
-in ca_cert.csr
: 这个选项指定了输入的证书请求文件。在这个例子中,证书请求文件的名称是ca_cert.csr
。 -
-signkey ca_key.pem
: 这个选项指定了用来签名证书的私钥文件。在这个例子中,私钥文件的名称是ca_key.pem
。 -
-out ca_cert.pem
: 这个选项指定了生成的证书的输出文件。在这个例子中,输出文件的名称是ca_cert.pem
。 -
-sigopt rsa_padding_mode:pss
: 这个选项指定了RSA签名的填充模式为PSS(Probabilistic Signature Scheme)。PSS是一种更安全的填充模式,它可以提供更好的安全性。(OCPP协议中要求的,见后文的A00.FR.505 For signing by the certificate authority RSA-PSS, or ECDSA SHOULD be used) -
-sigopt rsa_pss_saltlen:-1
: 这个选项指定了PSS填充的盐值长度。-1
表示自动选择最优的盐值长度。
所以,完成这几步,你应该已经得到了三个文件,ca_cert.pem(根证书)、ca_key.pem(根证书私钥)、ca_cert.csr(根证书签名请求)
4、生成客户端/服务端密钥对
因为客户端和服务端实际上生成证书的方法都是一样的,所以就放一起讲了。生成密钥的命令还是一样的,名字自己取就可以
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out client.key
参数和上面差不多,就不再赘述了
5、生成CSR
openssl req -new -key client.key -out client.pem -subj "/CN=序列号/O=制造商"
要注意一点:subj里面是用/分类的,不需要空格或者其他标点符号,参数也和上面一样,不再赘述
6、签署证书
openssl x509 -req -in client.csr -CA ca_cert.pem -CAkey ca_key.pem -CAcreateserial -out client.pem -days 365 -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1
-
-CA ca_cert.pem
: 这个选项指定了用来签名证书的CA(证书颁发机构)证书文件。在这个例子中,CA证书文件的名称是ca_cert.pem
。 -
-CAkey ca_key.pem
: 这个选项指定了用来签名证书的CA私钥文件。在这个例子中,CA私钥文件的名称是ca_key.pem
。 -
-CAcreateserial
: 这个选项告诉OpenSSL自动创建一个新的序列号文件,或者更新已有的序列号文件。序列号文件用来给每个证书分配一个唯一的序列号。 -
-out client.pem
: 这个选项指定了生成的证书的输出文件。在这个例子中,输出文件的名称是client.pem
。 -
-days 365
: 这个选项指定了证书的有效期为365天。 -
-sigopt rsa_padding_mode:pss
: 这个选项指定了RSA签名的填充模式为PSS(Probabilistic Signature Scheme)。PSS是一种更安全的填充模式,它可以提供更好的安全性。 -
-sigopt rsa_pss_saltlen:-1
: 这个选项指定了PSS填充的盐值长度。-1
表示自动选择最优的盐值长度。
至此为止,你应该拥有所有TLS链接需要的证书、密钥文件了
2.1.2 A00.FR.403
The CSMS SHALL verify the certification path of the Charging Station’s certificate according to the path validation rules established in Section 6 of [3]
CSMS 应根据 [3] 第 6 节中规定的路径验证规则验证充电站证书的验证路径。
首先要解释的是这个[3]是什么,这个[3]是Cooper, D., et al., Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile, Internet Engineering Task Force, Request for Comments 5280, May 2008, http://www.ietf.org/rfc/rfc5280.txt
其实就是参考文献。。。我们在其中可以了解第六节(Certification Path Validation)的内容来帮我们理解这个协议具体规定的验证规则是什么。
路径验证过程将验证以下内容:一个预期的认证路径(一系列的n证书)满足以下条件:
(a)对于{1,...,n-1}中的所有x,证书x的主题是证书 x+1 的颁发者;
(b)证书1由信任锚颁发;
(c)证书 n 是需要验证的证书(即目标证书);以及
(d)对于{1,...,n}中的所有x,证书在所涉时间。证书不得在预期中出现多次认证路径。
当信任锚以自签名形式提供时证书,此自签名证书不包含在预期认证路径。
意思基本就是这个意思,后面具体的算法我就不详细介绍了,其实就是要验证证书是否有问题,因为我们采用的是openssl的库或相关与它或以它为基础实现的库,所以我们不需要考虑这些路径,我们只需要考虑如何利用库去验证证书是否合法有效即可达成我们的目的。
2.1.3 A00.FR.404、A00.FR.405、A00.FR.406、A00.FR.407、A00.FR.408
The CSMS SHALL verify that the certificate is owned by the CSO (or an organization trusted by the CSO) by checking that the O (organizationName) RDN in the subject field of the certificate contains the CSO name.
The CSMS SHALL verify that the certificate belongs to this Charging Station by checking that the CN (commonName) RDN in the subject field of the certificate contains the unique serial number of the Charging Station (see Certificate Properties).
If the Charging Station certificate is not owned by the CSO, for instance immediately after installation it is RECOMMENDED to update the certificate before continuing communication with the Charging Station (also see Installation)
NOT A00.FR.429 AND If the Charging Station does not own a valid certificate, or if the certification path is invalid The CSMS SHALL terminate the connection.
A00.FR.407 OR A00.FR.429 It is RECOMMENDED to log a security event InvalidChargingStationCertificate in the CSMS.
CSMS 应通过检查证书主题字段中的 O(组织名称)RDN 是否包含 CSO 名称来验证证书 是否为 CSO(或 CSO 信任的组织)所有。CSMS 应通过检查证书主题字段中的 CN(公共名)RDN 是否包含充电站的唯一序列号(见证书属性)来验证证书是否属于该充电站。
如果充电站证书不属于 CSO,例如在安装后立即发现证书不属于 CSO ,建议更新证书后再继续与充电站通信(另请参阅安装)。 如果充电站没有有效证书,或认证路径无效 CSMS 必须终止连接。
A00.fr.407 或 A00.fr.429 建议记录安全事件 CSMS 中的无效充电站证书。
这其实就涉及到了一个新知识,主题;
一般的,证书包含的主题字段为:
-
国家(C):证书持有者的国家,通常使用两个字母的ISO 3166-1国家代码表示。
-
省份(ST):证书持有者所在的省份或地区。
-
城市(L):证书持有者所在的城市或地区。
-
组织(O):证书持有者的组织名称。
-
组织单位(OU):证书持有者的组织单位,例如部门。
-
通用名称(CN):证书持有者的通用名称,对于服务器证书,这通常是服务器的完全限定域名(FQDN)。
-
电子邮件地址(E):证书持有者的电子邮件地址。
这些主题字段一般来说都是非必须的,但是OCPP协议对于其中的O和CN是需要进行填写的,这是用赖标识充电站和云平台证书的有效字段
所以,一般地,O字段要填写带有CSO(充电站运营商)名称,CN字段要带有服务器的完全限定域名。
注:完全限定域名:比如我的网站主机名为be001a,域名为online,所以我的服务器完全限定域名为:be001a.online
证书验证失败后,CSMS肯定会主动终止这次TLS链接,无论是什么类型的程序都应如此进行。而OCPP协议中所说的安全事件记录,其实是为了给予云平台管理者一个安全日志存储,让管理者可以知道有多少次失败的链接(或许可以被视为攻击的防御成功)。
言归正传,我们一般的,可以通过openssl的x509库进行证书信息的查看和验证,如:
openssl x509 -in client.pem -text -noout
-
x509
:这是OpenSSL的一个子命令,用于显示和操作X.509证书。 -
-in client.pem
:这个选项指定输入文件,即你要查看的证书文件。 -
-text
:这个选项告诉OpenSSL以文本格式显示证书的详细信息,包括证书的主题,颁发者,有效期等。 -
-noout
:这个选项告诉OpenSSL不要输出编码后的证书信息,只输出文本信息。
一般来说,需要关注的字段为Signature Algorithm、Issure、Subject,上文其实都有简要提及,不在赘述。
2.1.4 A00.FR.409、A00.FR.410、A00.FR.411、A00.FR.412、A00.FR.413、A00.FR.414
The CSMS SHALL act as the TLS server.
The CSMS SHALL authenticate itself by using the CSMS certificate as server side certificate.
The Charging Station SHALL verify the certification path of the CSMS’s certificate according to the path validation rules established in Section 6 of [3].
The Charging Station SHALL verify that the commonName matches the CSMS’s FQDN.
If the CSMS does not own a valid certificate, or if the certification path is invalid The Charging Station SHALL trigger an InvalidCsmsCertificate security event (See part 2 appendices for the full list of security events).
If A00.FR.413 The Charging Station SHALL terminate the connection.
CSMS 应充当 TLS 服务器。CSMS 必须使用 CSMS 证书作为服务器端证书来验证自己。
充电站应根据 [3] 第 6 节中规定的路径验证规则验证 CSMS 证书的认证路径。
充电站应验证公共名是否与 CSMS 的 FQDN 一致。
如果 CSMS 没有有效证书,或认证路径无效 充电站应触发 InvalidCsmsCertificate 安全事件(有关安全事件的完整列表,请参阅第 2 部分附录),充电站应终止连接。
云平台应该充当TLS链接中的server端,这是必然的,不再过多赘述。关于必须使用服务器端的证书来验证自己,我是这样理解的:我需要通过根证书和服务器端的证书去验证当前的服务器端证书是否是有效的,自己的证书如果无效了,当然要终止连接。
python中,我们建立一个ssl上下文之后,才可以进行TLS链接。
import ssl
cafile = "ssl/ca_cert.pem"
certfile = "ssl/server.pem"
keyfile = "ssl/server.key"
ssl_context = ssl.create_default_context(
ssl.Purpose.CLIENT_AUTH,
cafile = cafile,
)
ssl_context.check_hostname = False
ssl_context.load_cert_chain(
certfile=certfile,
keyfile=keyfile,
)
ssl_context.verify_mode = ssl.CERT_REQUIRED
-
ssl.create_default_context
为了创建基本上下文,因为我是平台,所以要建立对客户端的验证,所以ssl.Purpose.CLIENT_AUTH
,cafile
就是ca根证书位置 -
check_hostname
是配置是否检查主机名,我暂时还没用到这一项,所以现在是False
-
load_cert_chain
中是为了将服务端根证书和服务端密钥加载进来,以便于验证 -
verify_mode
是验证模式,我这里写的是ssl.CERT_REQUIRED
就是必须认证证书,如果客户端/服务端有一方面不想选择认证证书,只需要把这个写为ssl.CERT_NONE
即可
其余的事情,其实就应该为充电站去做了,比如验证公共名是否与 CSMS 的 FQDN 一致和路径验证,其余的代码其实都一样,只需要把ssl.Purpose.CLIENT_AUTH
修改为ssl.Purpose.SERVER_AUTH
即可。
注:别忘了,建立TLS链接的websocket的时候,我们应该将ws改为wss。
2.1.5 A00.FR.415、A00.FR.416、A00.FR.417、A00.FR.418、A00.FR.419、A00.FR.420
The communication channel SHALL be secured using Transport LayerSecurity (TLS) [4].
The Charging Station and CSMS SHALL only use TLS v1.2 or above.Both of these endpoints SHALL check the version of TLS used.
A00.FR.417 AND The CSMS detects that the Charging Station only allows connections using an older version of TLS, or only allows SSL, The CSMS SHALL terminate the connection.
A00.FR.417 AND The Charging Station detects that the CSMS only allows connections using an older version of TLS, or only allows SSL, The Charging Station SHALL trigger an InvalidTLSVersion security eventAND terminate the connection (See part 2 appendices for the full list ofsecurity events).
TLS SHALL be implemented as in [4] or its successor standards without any modifications.
通信通道应使用传输层安全协议(TLS)[4] 确保安全。充电站和 CSMS 只能使用 TLS v1.2 或更高版本。这两个端点都必须检查所使用的 TLS 版本。
A00.FR.417 和 CSMS检测到充电站只允许使用旧版本的TLS 进行连接,或只允许使用 SSL 进行连接, CSMS必须终止连接。
A00.FR.417 和 充电站检测到CSMS只允许使用旧版本的TLS 进行连接,或只允许使用 SSL 进行连接, 充电站应触发 InvalidTLSVersion 安全事件并终止连接(有关安全事件的完整列表,请参阅第 2 部分附录)。
TLS 应按照 [4] 或其后续标准实施,不得做任何修改。
采用TLS不用多说,我们一直在说这件事。OCPP要求充电站和云平台使用的TLS版本TLS v1.2或更高版本,那就涉及到了一个技术问题:如何看这个版本呢?
我们可以采用python的websockets库的一些函数进行处理。
ssl_object = websocket.transport.get_extra_info('ssl_object')
if ssl_object:
# 获取TLS版本
tls_version = ssl_object.version()
tls_version_number = tls_version.replace('TLSv1.', '')
if int(tls_version_number) < 2:
logging.error("TLS version is not supported")
return await websocket.close()
logging.info("TLS version: %s", tls_version)
这里我们可以看到,我们采用了websockets报文解析的方法来获取ssl对象,通过这个对象的.version()
方法来获取ssl的版本号信息。如果TLS小于1.2版本,我们就关闭链接,充电站的实现方式也差不太多,都是这样去获取版本号信息的,但是我这里只是简单的例子哈~
最后说的[4]其实就是TLS1.2的标准信息规定了,我们无需关注,因为伟大的openssl已经帮我们实现完毕了(感谢他),但如果你对这个有兴趣,你也可以去看看它。
2.1.6 A00.FR.421、A00.FR.422、A00.FR.423
The CSMS SHALL support at least the following four cipher suites: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_RSA_WITH_AES_128_GCM_SHA256 TLS_RSA_WITH_AES_256_GCM_SHA384 Note: The CSMS will have to provide 2 different certificates to support both cipher suites. Also when using security profile 3, the CSMS should be capable of generating client side certificates for both cipher suites.
The Charging Station SHALL support at least the cipher suites: (TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 AND TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) OR (TLS_RSA_WITH_AES_128_GCM_SHA256 AND TLS_RSA_WITH_AES_256_GCM_SHA384) Note 1: TLS_RSA does not support forward secrecy, therefore TLS_ECDHE is RECOMMENDED. Furthermore, if the Charging Station detects an algorithm used that is not secure, it SHOULD trigger an InvalidTLSCipherSuite security event (See part 2 appendices for the full list of security events). Note 2: Please note that ISO15118-2 prescribes to implement the following cipher suites for the communication between EV and Charging Station: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
The Charging Station and CSMS SHALL NOT use cipher suites that use cryptographic primitives marked as unsuitable for legacy use in [1]. This will mean that when one (or more) of the cipher suites described in this specification becomes marked as unsuitable for legacy use, it SHALL NOT be used anymore.
CSMS 应至少支持以下四种密码套件: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_RSA_WITH_AES_128_GCM_SHA256 TLS_RSA_WITH_AES_256_GCM_SHA384 注意:CSMS 必须提供两种不同的证书,以支持两种密码套件。此外,在使用安全配置文件 3 时,CSMS 应能为两种密码套件生成客户端证书。
充电站应至少支持以下密码套件:( TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 和 tls_ecdhe_ecdsa_with_aes_256_gcm_sha384)或 (TLS_RSA_WITH_AES_128_GCM_SHA256 AND TLS_RSA_WITH_AES_256_GCM_SHA384) 注 1:TLS_RSA 不支持前向保密,因此推荐使用 TLS_ECDHE。此外,如果充电站检测 到所使用的算法不安全,则应触发 InvalidTLSCipherSuite 安全事件(完整的安全事件 请参见第 2 部分附录)。 安全事件列表)。 注 2:请注意,ISO15118-2 规定电动汽车和充电设备之间的通信必须使用以下密码套件 车站: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
充电站和 CSMS 不得使用在 [1] 中被标记为不适合传统使用的密码套件。这意味着当本 规范中描述的一个(或多个)密码套件被标记为不适合传统使用时,不得再使用该密码套件 。
理论上来讲,想让CSMS支持多种套件,只需要在openssl的上下文中设置好即可
context.set_ciphers('ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:RSA-AES128-GCM-SHA256:RSA-AES256-GCM-SHA384')
但是不仅仅如此,设置了其他密码套件意味着你需要设置其他的证书,和上方加载证书的方法其实是一致的,都是利用load_cert_chain
方法即可
那么,以此类推,充电站方面也是一样的。
关于传统密码套件,我的建议是你用最新的,最新的肯定没毛病~
2.1.7 A00.FR.424、A00.FR.425、A00.FR.426、A00.FR.427、A00.FR.428、A00.FR.429、
The Charging Station and CSMS SHALL NOT use cipher suites that use cryptographic primitives marked as unsuitable for legacy use in [1]. This will mean that when one (or more) of the cipher suites described in this specification becomes marked as unsuitable for legacy use, it SHALL NOT be used anymore.
The TLS Server and Client SHALL NOT use TLS compression methods to avoid compression side-channel attacks and to ensure interoperability as described in Section 6 of [10].
A00.FR.424 AND If the CSMS detects that the Charging Station only allows connections using one of these suites, The CSMS SHALL terminate the connection.
A00.FR.424 AND The Charging Station detects that the CSMS only allows connectionsusing one of these suites, The Charging Station SHALL trigger an InvalidTLSCipherSuite securityevent AND terminate the connection (See part 2 appendices for the full listof security events).
A unique Charging Station certificate SHALL be used for each Charging Station.
The Charging Station Certificate MAY be the same certificate as the SECC Certificate in ISO15118-2, used to set up a TLS connection between the Charging Station and an Electric Vehicle.
If Charging Station certificate has been expired AND CSMS has been explicitly configured to accept a connection by this specific Charging Station with an expired certificate. CSMS MAY accept this Charging Station in a BootNotification - Pending state (use case B02) after which it SHALL immediately execute A02 - Update Charging Station Certificate by request of CSMS to renew the certificate.
TLS 服务器和客户端不得使用 TLS 压缩方法,以避免压缩侧信道攻击,并确保 [10] 第 6节所述的互操作性。 A00.FR.424 和 如果 CSMS 检测到充电站 只允许使用特定的密码套件进行连接CSMS 必须终止连接。 A00.FR.424 和 充电站检测到 CSMS 只允许使用特定的密码套件进行连接充电站应触发 InvalidTLSCipherSuite 安全事件并终止连接(有关安全事件的完整列表,请参阅第 2 部分附录)。
每个充电站必须使用唯一的充电站证书。充电站证书可能与 ISO15118-2 中的 SECC 证书相同,用于在充电站和电动汽车之间建立TLS 连接。 如果充电站证书已过期,并且CSMS 已被明确配置为接受该特定充电站使用过期证书进行的连接。CSMS 可以接受处于 BootNotification - Pending 状态(用例 B02)的充电站,之后应立即执行 A02 - 更新充电站证书,请求 CSMS 更新证书。
看到这,不得不简单介绍一下,啥叫TLS压缩了。TLS压缩是一种在传输层安全性(TLS)协议中使用的技术,它可以减少在网络上发送的数据量。这是通过在数据发送到网络之前对其进行压缩来实现的。然后,接收方在接收到数据后对其进行解压缩。然而,TLS压缩已经被证明是不安全的,因为它可能会导致CRIME(Compression Ratio Info-leak Made Easy)和BREACH(Browser Reconnaissance and Exfiltration via Adaptive Compression of Hypertext)等侧信道攻击。这些攻击利用了压缩算法的特性,通过观察压缩后的数据长度来推断原始数据的内容。因此,现代的TLS实现通常不再支持压缩,以提高安全性。例如,Python的SSL模块默认禁用了TLS压缩。
密码套件的不再赘述,其实就是不能只支持特定的密码套件,需要至少支持四种才可以
若充电站证书已经过期,那么应该先更新证书再进行重新连接,保证连接的安全。
到此为止,A00.FR.4部分也就是需要带客户端证书的TLS就介绍完了,下面其实是一些扩展性的内容,专门针对于证书的。
2.2 证书属性
2.2.1 ocpp使用的证书
其实,ocpp协议中只使用了四种证书:CSMS 证书、充电站证书、固件签名证书、SECC 证书。这四种证书对应的密钥存储位置分别在CSMS、充电站、制造商、充电站。
2.2.2 证书的属性要求
首先要讲的是,所有的证书都必须使用私钥,并且,私钥至少是112位加密(还记不记得rsa_keygen_bits:3072
了?),然是如果使用rsa的方式进行加密(我们当前使用的),至少要2048位的密钥长度。
证书颁发机构在签发证书签署签名的时候,应使用RSA-PSS 或 ECDSA 进行签名,这是两种签名算法,我们只需要会使用就可以了~
而且,在固件升级包签名的时候,应该使用SHA256算法去计算固件升级包文件的哈希值,当然不仅仅只限于这个地方使用哈希值,后续要是遇到了我会提一嘴的
证书的存储方式应采用PEM格式的X509格式存储和传输,也就是说你需要使用x509格式的证书,并且传输证书和存储证书的文件后缀名应该为.pem。
所有的证书都必须需要有序列号,证书的主题字段必须包含organizationName,字段中必须包含证书所有者的组织名称。服务器证书中需要包含CN,CN中要包含服务器端点的FQDN(没忘吧,完全限定域名)。充电站证书的主题字段也要包含CN,但是它的CN由充电站的唯一序列号组成,它一般来说是充电站的SN码。
2.2.3 证书的安装要求
ocpp建议制造商在制造充电站时使用唯一凭证进行初始化,凭证应使用加密随机数生成器生成,并安装在安全的环境中,这些信息应通过安全通道发送给 CSO(充电站运营商),以便 CSO 将其导入 CSMS,制造商可以使用自己的证书签署这些证书文件。
更新充电站出场证书之前,CSMS可以限制充电站的功能,在boot通知的时候回复Pending,更新了证书重新连接后才可以正常交互。
若充电站证书已经过期了,和上述内容一样的做法,更新了证书重新连接后才可以正常交互。
2.3 A02 - 应 CSMS 的要求更新充电站证书
说到这,说到点子上了,真正的数据交互。我们在上面首次提到的其实就是这个case,要更新充电站证书,流程如下(截取自ocpp):
流程比较简单,但是需要实践得真知(代码的实现逻辑我就不写了,我只写伪代码来表述一下~)。
首先,CSMS要告诉充电站,你需要更新你的证书了,你就会通过json消息发送过去一个:
[2, "ad82d570-41f0-4596-9ffb-30be580bc363", "TriggerMessage",{}]
然后充电站应该回复:
[3, "ad82d570-41f0-4596-9ffb-30be580bc363", {"status": "Accepted"}]
充电站接受了之后,就要通过openssl库生成新的密钥了,所以需要执行
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out ca_key.pem
然后会将这个生成的key里面的内容通过SignCertificateRequest的json消息发送给平台,像是这样:
[2, "ecc19fe3-853b-4c2f-be22-519161921514", "SignCertificate", {
"csr": "-----BEGIN CERTIFICATE REQUEST-----\nMIIBkzCCATQCAQAwgYExCzAJBgNVBAYTAkNOMQswCQYDVQQIDAJDQTEQMA4GA1UEBwwHUmVkbW9uZDEPMA0GA1UECgwGQ2hhcmdpbjEQMA4GA1UECwwHUmVkbW9uZDEPMA0GA1UEAwwGQ2hhcmdpbjAeFw0yMTA0MjMxNzQwMzdaFw0yMjA0MjMxNzQwMzdaMIGEMQswCQYDVQQGEwJDTjELMAkGA1UECAwCQ0ExEDAOBgNVBAcMB1JlZG1vbmQxDzANBgNVBAoMBkNoYXJnaW4xEDAOBgNVBAsMB1JlZG1vbmQxDzANBgNVBAMMBkNoYXJnaW4wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS3\n-----END CERTIFICATE REQUEST-----\n",
"certificateType": "ChargingStationCertificate"
}]
云平台收到并且解析后,就会回复一个相应的接受或拒绝(一般不会):
[3, "ecc19fe3-853b-4c2f-be22-519161921514", {"status": "Accepted"}]
然后,云平台会将充电站发过来的CSR转发到证书颁发服务器,因为我是自签名的,所以就是给我自己,然后使用这个CSR签署证书,过程和最开始的一样,我就不再多说了,然后将生成出来的新证书发送回充电站:
[2,"559769ca-3913-43d1-898c-41c0fbf72acd","CertificateSigned",{"certificateChain":"-----BEGIN CERTIFICATE-----\nMIIEODCCAmwCFAHz0Xk3vUKF0zjmSgAjURYyiNc7MEEGCSqGSIb3DQEBCjA0oA8w\nDQYJYIZIAWUDBAIBBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAIBBQCiAwIB\nIDAYMRYwFAYDVQQDDA1iZTAwMWEub25saW5lMB4XDTI0MDUzMDA4NTAyOVoXDTI1\nMDUzMDA4NTAyOVowMTELMAkGA1UEBhMCQ04xDDAKBgNVBAoMA0JKQjEUMBIGA1UE\nAwwLMDk4NzY1NDMyMTAwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCh\nOjhM42vFsDhBPJnA9zgUgW1Ywq8bw6F9YWDQyrJ0TdIl7LNiWNXc0Y2Qm8qs7ydY\nLJx81XaOslibZJkEltL5dpKqRo6/01oAtd0OX3Y8xsEDL7TXJSRxvowqhamtr7jM\nVb2kJy5J27Os7wXkvmKKpy2Q+FHsXa2ZNyASA9rSUKibF+JqoIUxPkEKpKF2OgxI\n5kI7wTqCItG7d6FOVDa+9MZhV+187Oj3SDo19c8J7DUG7TkpZTdWuNtOADNj74oM\nYZuofSBFwuhPjMIdKj8KSxUKNS03yJZN4yLEsNjSrjWOIYpep2OJISKV7080ipj5\ntX7/zR4AiuEszZ93c/ygRu+nfawq/kWTKvDRHzolmQJ/ftwnuz24ZxnQvB0Ad3FV\npe9Wd8HD7KitsEOysKPnf1JMNmIxqE7mY0wOcQz15E7K1UgD23aT1PVOPHuejxpr\nXJJSPYNAxgRoscTdP5ed6Y2GlT9U6IAQxnzUbmBMaMp10Tp4ySvR2fLlzJIS56sC\nAwEAATBBBgkqhkiG9w0BAQowNKAPMA0GCWCGSAFlAwQCAQUAoRwwGgYJKoZIhvcN\nAQEIMA0GCWCGSAFlAwQCAQUAogMCASADggGBAHAhKMCDLq1FQIGVln4xzAJQTf3I\nXVXzzt0y8soyaDUjwAf3pY99JiYX1+PJjdjnCXhNrS/i3X33JNiiBzJXR2XTnETR\n5JTEkG7UaQVIN3rjEQ3sPkewRZqz4ZqdjDpQIuB6blhshij/LLsfSLzKgS4wgCEs\njveXxonuJHI5l6dIM6WWiW1RgNvE/krJbi9u/Ui+AQCglWCAhJGQ/La7rNm75E/m\nqLrWxHBjIq7GujVd9QsNh19S0hrklCvXn6IVLT4NNY+L6LcJUQNNpe6PtlBfi4JS\njsBJO2mlZJm76pzKjWrbp5xFDpqr6wgdd8tWKdcMOWEQbBJSNNbSc/Ml2QtWVepr\nAC53n2KIh/+3TxKcbGIqGkH/vRNH6OAuxR3BBS+qPivHlOUe1NcZAxU5md2v/BUA\nOFGN3jopIA/MmuygBzrCyZOLkRBC3EjVUvJ6iFu+Tk+x7SN/Fla9XRwoVSLInfeE\nVi/VBMrhgBAPfIcX0DIctbpt4vlb06EEqgsMMA==\n-----END CERTIFICATE-----\n","certificateType":"ChargingStationCertificate"}]
最后,充电站拿到了新的证书,就可以使用新的证书重新建立连接啦,整个过程就结束了~
正常的逻辑其实已经结束了,但是看过ocpp的人都知道(或者现在我告诉你),在流程下面的需求更是我们需要注意的,那么我们聚焦以下需求这方面:
1、充电站安装后应进行密钥更新,以更改制造商最初提供的密钥(可能是默认密钥),也就是说,充电站首次上电进行boot_notification的时候,就应该更新你的密钥了,不可以继续使用充电站的出厂默认密钥。
2、充电站回复完CSMS TriggerMessageResponse之后,应该按照一定的规则生成新的公钥和私钥对,然后生成新的CSR,并且使用SignCertificateRequest信息发送给CSMS,其中的csr字段要符合PEM格式的编码。
3、正常来说,CSMS不应该自行签署证书,而是应该将CSR转发到管理充电站基础设施证书的专用证书授权服务器,专用授权服务器可由 CSO 运营,而且无论任何时候,充电站生成的公钥和私钥都不能离开充电站,也不能通过任何其他外部手段直接进行获取。
4、充电站应该验证SignCertificateResponse中证书的有效性,可以通过根证书来进行验证,至少检查证书有效 期、证书属性中的属性,以及证书层次结构中描述的充电站操作员证书层次结构的一部分。
5、如果验证出证书是无效的,充电站必须立刻以status=“Reject”的形式回复CSMS,并且立刻丢弃证书,触发安全事件中的InvalidChargingStationCertificate。、
6、如果充电站更新了新证书,建议立刻断开当前的连接,并且使用新的证书进行与CSMS的连接。但是,也同时建议将就证书留存一个月,作为备用证书进行使用。
其余的要求也许涉及不到,也许涉及V2G(双向能量传输),也许涉及欧标充电标准(ISO15118),我就不继续赘述了,因为咱也不太懂哈哈哈~
2.4 A03 - 由充电站启动更新充电站证书
这部分其实是以充电站为主导的更新证书,因为大概流程比较相似,我这边暂时只介绍报文的交互,其余的不再多加赘述了~ocpp协议上的截图如下:
翻译以下流程:
-
1.充电站检测到充电站证书到期。
-
2.充电站生成新的公钥/私钥对。
-
3.充电站向CSMS发送SignCertificateRequest,其中包含适用的 CertificateSigningUse.
-
4. CSMS以SignCertificateResponse响应,状态为Accepted。
-
5. CSMS将CSR转发到证书颁发机构服务器。
-
6.证书颁发机构服务器签署证书。
-
7.证书颁发机构服务器将签名证书返回给CSMS。
-
8. CSMS向充电站发送CertificateSignedRequest。
-
9.充电站验证签名证书。
-
10.充电站向CSMS发送CertificateSignedResponse,状态为 接受或拒绝。
其实,这就是主要的交互流程了,所以我们首先应该知道,要如何检测充电站证书什么时候到期?多长时间检测一次?
检测的方式很简单,其实就是通过openssl的库进行即可,也就是说,我们可以采用以下的命令:
openssl x509 -enddate -noout -in client.pem
输出为:
notAfter=Jun 3 09:16:42 2025 GMT
这就代表2025年06月03日会过期。按照正常的ocpp协议中来看,也没有详细规定这个事情,但是一般证书都是一年左右有效期,我们可以考虑的是每个月检验一次,如果获取到的这个有效期的时间还有一个月就要到了,我们充电站应该主动执行此case:A03来更新充电站的证书。
那么言归正传, 我也应该继续叙述消息交互大概是什么样的了。
首先是1、2结束后,充电站发送SignCertificateRequest,其中certificateType = ChargingStationCertificate。
[2, "ecc19fe3-853b-4c2f-be22-519161921514", "SignCertificate", {
"csr": "-----BEGIN CERTIFICATE REQUEST-----\nMIIBkzCCATQCAQAwgYExCzAJBgNVBAYTAkNOMQswCQYDVQQIDAJDQTEQMA4GA1UEBwwHUmVkbW9uZDEPMA0GA1UECgwGQ2hhcmdpbjEQMA4GA1UECwwHUmVkbW9uZDEPMA0GA1UEAwwGQ2hhcmdpbjAeFw0yMTA0MjMxNzQwMzdaFw0yMjA0MjMxNzQwMzdaMIGEMQswCQYDVQQGEwJDTjELMAkGA1UECAwCQ0ExEDAOBgNVBAcMB1JlZG1vbmQxDzANBgNVBAoMBkNoYXJnaW4xEDAOBgNVBAsMB1JlZG1vbmQxDzANBgNVBAMMBkNoYXJnaW4wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS3\n-----END CERTIFICATE REQUEST-----\n",
"certificateType": "ChargingStationCertificate"
}]
然后,CSMS收到了后,就会回复:
[3, "ecc19fe3-853b-4c2f-be22-519161921514", {"status": "Accepted"}]
然后,云平台会将充电站发过来的CSR转发到证书颁发服务器,因为我是自签名的,所以就是给我自己,然后使用这个CSR签署证书,过程和最开始的一样,我就不再多说了,然后将生成出来的新证书发送回充电站:
[2,"559769ca-3913-43d1-898c-41c0fbf72acd","CertificateSigned",{"certificateChain":"-----BEGIN CERTIFICATE-----\nMIIEODCCAmwCFAHz0Xk3vUKF0zjmSgAjURYyiNc7MEEGCSqGSIb3DQEBCjA0oA8w\nDQYJYIZIAWUDBAIBBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAIBBQCiAwIB\nIDAYMRYwFAYDVQQDDA1iZTAwMWEub25saW5lMB4XDTI0MDUzMDA4NTAyOVoXDTI1\nMDUzMDA4NTAyOVowMTELMAkGA1UEBhMCQ04xDDAKBgNVBAoMA0JKQjEUMBIGA1UE\nAwwLMDk4NzY1NDMyMTAwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCh\nOjhM42vFsDhBPJnA9zgUgW1Ywq8bw6F9YWDQyrJ0TdIl7LNiWNXc0Y2Qm8qs7ydY\nLJx81XaOslibZJkEltL5dpKqRo6/01oAtd0OX3Y8xsEDL7TXJSRxvowqhamtr7jM\nVb2kJy5J27Os7wXkvmKKpy2Q+FHsXa2ZNyASA9rSUKibF+JqoIUxPkEKpKF2OgxI\n5kI7wTqCItG7d6FOVDa+9MZhV+187Oj3SDo19c8J7DUG7TkpZTdWuNtOADNj74oM\nYZuofSBFwuhPjMIdKj8KSxUKNS03yJZN4yLEsNjSrjWOIYpep2OJISKV7080ipj5\ntX7/zR4AiuEszZ93c/ygRu+nfawq/kWTKvDRHzolmQJ/ftwnuz24ZxnQvB0Ad3FV\npe9Wd8HD7KitsEOysKPnf1JMNmIxqE7mY0wOcQz15E7K1UgD23aT1PVOPHuejxpr\nXJJSPYNAxgRoscTdP5ed6Y2GlT9U6IAQxnzUbmBMaMp10Tp4ySvR2fLlzJIS56sC\nAwEAATBBBgkqhkiG9w0BAQowNKAPMA0GCWCGSAFlAwQCAQUAoRwwGgYJKoZIhvcN\nAQEIMA0GCWCGSAFlAwQCAQUAogMCASADggGBAHAhKMCDLq1FQIGVln4xzAJQTf3I\nXVXzzt0y8soyaDUjwAf3pY99JiYX1+PJjdjnCXhNrS/i3X33JNiiBzJXR2XTnETR\n5JTEkG7UaQVIN3rjEQ3sPkewRZqz4ZqdjDpQIuB6blhshij/LLsfSLzKgS4wgCEs\njveXxonuJHI5l6dIM6WWiW1RgNvE/krJbi9u/Ui+AQCglWCAhJGQ/La7rNm75E/m\nqLrWxHBjIq7GujVd9QsNh19S0hrklCvXn6IVLT4NNY+L6LcJUQNNpe6PtlBfi4JS\njsBJO2mlZJm76pzKjWrbp5xFDpqr6wgdd8tWKdcMOWEQbBJSNNbSc/Ml2QtWVepr\nAC53n2KIh/+3TxKcbGIqGkH/vRNH6OAuxR3BBS+qPivHlOUe1NcZAxU5md2v/BUA\nOFGN3jopIA/MmuygBzrCyZOLkRBC3EjVUvJ6iFu+Tk+x7SN/Fla9XRwoVSLInfeE\nVi/VBMrhgBAPfIcX0DIctbpt4vlb06EEqgsMMA==\n-----END CERTIFICATE-----\n","certificateType":"ChargingStationCertificate"}]
然后,充电站要表明是否接受,回复response:
[3, "559769ca-3913-43d1-898c-41c0fbf72acd", {"status": "Accepted"}]
最后,充电站拿到了新的证书,就可以使用新的证书重新建立连接啦,整个过程就结束了~
正常流程后肯定就是详细要求,我总结一小下:
1、充电站冷启动后就可以触发这个事件来更新充电站的证书,用来替换掉出厂的默认证书
2、充电站检测到证书将在一个月之内到期的时候,应该重新获取和生成新的证书。
3、充电站应以证书的形式发送公钥 签名请求(CSR),如RFC 2986 [22]中所述,然后是使用PEM进行编码 SignCertificateRequest消息。
4、CSMS不应该自己签署证书,而是转发 将CSR发送到专用证书颁发机构服务器, 充电站基础设施的证书。专用 授权服务器可以由CSO操作。但由于我的测试环境没有服务器,所以我就全都是自签自用。
5、在密钥更新期间由充电站生成的私钥任何时候都不得离开充电站, 不可通过OCPP或任何其他(远程)通信读取,绝对不允许任何方式让私钥泄漏。
6、充电站应验证签名证书的有效性, CertificateSignedRequest消息,至少检查证书有效性,证书属性中的属性,并且它是充电站运营商证书层级的一部分。
7、如果证书无效。充电站应响应CertificateSignedRequest 状态为已拒绝并丢弃证书并触发 InvalidChargingStationCertificate安全事件。
8、充电站应尽快切换到新证书, 当前日期和时间在证书中的“之前无效”字段之后 (e.g.通过关闭WebSocket和TLS连接并使用新证书重新连接)。
9、如果充电站包含超过一份有效的充电站证书类型,充电站应使用最新的证书。
2.5 A04 - 安全事件通知
这个case的流程相对来说就比较简单,就是在发生安全事件的时候,充电站立即通知CSMS系统安全性的变化。流程如下(同流程图)
-
1. 发生重大安全事件。
-
2.充电站向CSMS发送SecurityEventNotificationRequest。
-
3.CSMS使用SecurityEventNotificationResponse响应充电站。
对于这个重大安全事件,OCPP告诉我们可以去附录1中去看,我们可以根据他所说的进行评估,截图如下:
-
这部分的详细要求就很简单,发生安全事件必须要发送给云平台。
-
发生安全事件以及充电站断开链接了之后,安全事件通知要在云平台上排队,并且保证送达。
-
CSMS 应使用SecurityEventNotificationResponse消息确认 收到通知。
-
充电站应将安全事件存储在安全日志中
2.6 A05 - 升级充电站安全配置文件
流程如下:
-
1. CSMS 通过 SetVariablesRequest 为 NetworkConfigurationPriority 配置变量设置一个新值,以便新(更高)安全配置文件的 NetworkConnectionProfile 成为列表中的第一个,现有连接配置文件成为列表中的第二个。
-
2. 充电站以 SetVariablesResponse 响应,状态为 Accepted
-
3.CSMS 发送 ResetRequest(OnIdle)
-
4。充电站重新启动并通过新的主 NetworkConnectionProfile 进行连接
事实上,就是需要充电站更换安全配置文件中的网络链接配置文件,将现有的配置文件的优先级滞后,拿到的新文件的优先级放到最前面,然后充电站重新连接,重新发送boot通知
这部分的详细要求就是需要对一些变量和组件进行详细要求,我这边就不多去讲了,因为我主要是考虑流程(就是因为我懒)
好了,整个A部分的介绍就写完了,断断续续写了好久,后面的更复杂的可能我更新的更慢哈哈哈哈