使用 OpenSSL 使用 QCStatements 创建证书

Create certificate with QCStatements using OpenSSL

我想创建模拟 CA 并设置 QCStatements 扩展,但找不到有关使用 OpenSSL 设置它的任何信息。我正在寻找我发现一些旧主题,人们在其中寻找这些信息,但没有人回答。是否可以使用 openSSL 设置 QCStatements?

如果有人遇到同样的问题,我找到了解决方案。我使用开源应用程序 ejbca app. There is a qcStatement section in this app:

通过 qcStatement 创建了证书

使用纯 openssl 是可能的。您必须使用所有必需的 qcStatements 信息为签名请求创建配置,然后使用证书复制请求的扩展名。

示例配置文件

[req]
distinguished_name = req_distinguished_name
req_extensions = qcStatements

[req_distinguished_name]

[qcStatements]
1.3.6.1.5.5.7.1.3=ASN1:SEQUENCE:qcStatement

[qcStatement]
etsiQcsCompliance=SEQUENCE:etsiQcsCompliance
qcs-QcPDS=SEQUENCE:qcs-QcPDS
id-qc-statement=SEQUENCE:id-qc-statement
qcs-QcType=SEQUENCE:qcs-QcType
[etsiQcsCompliance]
statementId=OID:0.4.0.1862.1.1
[qcs-QcPDS]
statementId=OID:0.4.0.1862.1.5
QcPDS-List=SEQUENCE:QcPDS-List
[QcPDS-List]
QcPDS1=SEQUENCE:QcPDS1
[QcPDS1]
url=IA5STRING:https://example.org/pkidisclosure
description=PRINTABLESTRING:example

[id-qc-statement]
statementId=OID:0.4.0.19495.2
statementInfo=SEQUENCE:id-qc-statement-Info
[id-qc-statement-Info]
rolesOfPSP=SEQUENCE:rolesOfPSP
nCAName=UTF8String:Dummy Financial Supervision Authority
nCAId=UTF8String:XX-DFSA
[rolesOfPSP]
PSP_AI=SEQUENCE:PSP_AI
PSP_AS=SEQUENCE:PSP_AS
PSP_PI=SEQUENCE:PSP_PI
PSP_IC=SEQUENCE:PSP_IC
[PSP_AI]
roleOfPspOid=OID:0.4.0.19495.1.3
roleOfPspName=UTF8String:PSP_AI
[PSP_AS]
roleOfPspOid=OID:0.4.0.19495.1.1
roleOfPspName=UTF8String:PSP_AS
[PSP_PI]
roleOfPspOid=OID:0.4.0.19495.1.2
roleOfPspName=UTF8String:PSP_PI
[PSP_IC]
roleOfPspOid=OID:0.4.0.19495.1.4
roleOfPspName=UTF8String:PSP_IC
[qcs-QcType]
statementId=OID:0.4.0.1862.1.6
statementInfo=SEQUENCE:qcs-QcType-Info
[qcs-QcType-Info]
qct-esign=OID:0.4.0.1862.1.6.1
qct-eseal=OID:0.4.0.1862.1.6.2
qct-web=OID:0.4.0.1862.1.6.3

您必须将配置应用于签名请求

openssl req -new -key dummy.key -out dummy.csr -subj /C=XX/CN=dummy -config qcstatements.conf

然后使用从 CA 配置文件中的请求复制扩展名的选项进行签名。

copy_extensions = copy

特别感谢 AGrzes - 你真的让我走上了正确的道路。

我花了很多时间搜索所有这些相关标准,所以我想我会提供帮助,post 在这里为大家省去麻烦。

当我进行 ASN.1 工作时,我通常会仔细阅读 https://censys.io/certificates 来检查我的代码是否与现有证书匹配。总能帮我节省时间。记下您的查询结果中有多少证书 - 人们会犯错误,因此您可能会走错路。

无论如何,我的openssl-RFC3739.cnf:

#Qualified Certificate Profiles / Payment Services Directive / ETSI / eIDAS
#TODO: implement: biometricInfo: typeOfBiometricData = OID:(finger/palm/retina/voice OID under my_pen OID arc)
#TEST: \
  export OPENSSL_CONF=openssl-RFC3739.cnf;         #use this conf \
  openssl asn1parse -genstr OID:1.3.6.1.5.5.7.1.3; #check OID support \
  openssl req -x509 -nodes -newkey ec -pkeyopt ec_paramgen_curve:secp384r1 -keyout key.pem -out cert.pem -batch;                              #generate public/prive keys \
  openssl asn1parse -in cert.pem | sed -n '/qcStatements/{n;s/.*://p}' | xxd -r -p | openssl asn1parse -inform DER -i;                        #show qcStatements \
  openssl asn1parse -in cert.pem | sed -n '/Biometric Info/{n;s/.*://p}' | xxd -r -p | openssl asn1parse -inform DER -i;                      #shox biometricInfo \
  openssl asn1parse -in cert.pem | sed -n '/X509v3 Subject Directory Attributes/{n;s/.*://p}' | xxd -r -p | openssl asn1parse -inform DER -i; #show subjectDirectoryAttributes \
  openssl asn1parse -in cert.pem | sed -n '/cabfOrganizationIdentifier/{n;s/.*://p}' | xxd -r -p | openssl asn1parse -inform DER -i;          #show cabfOrganizationIdentifier \
#https://censys.io/certificates?q=parsed.unknown_extensions.id%3A+1.3.6.1.5.5.7.1.3                                                           #example certs using this OID
#ETSI EN 319 412-1 V1.4.2 (2020-07) - https://www.etsi.org/deliver/etsi_en/319400_319499/31941201/01.04.02_20/en_31941201v010402a.pdf
#ETSI EN 319 412-2 V2.2.1 (2020-07) - https://www.etsi.org/deliver/etsi_en/319400_319499/31941202/02.02.01_60/en_31941202v020201p.pdf
#ETSI EN 319 412-3 V1.2.1 (2020-07) - https://www.etsi.org/deliver/etsi_en/319400_319499/31941203/01.02.01_60/en_31941203v010201p.pdf
#ETSI EN 319 412-4 V1.1.1 (2016-02) - https://www.etsi.org/deliver/etsi_en/319400_319499/31941204/01.01.01_60/en_31941204v010101p.pdf
#ETSI EN 319 412-5 V2.3.1 (2020-04) - https://www.etsi.org/deliver/etsi_en/319400_319499/31941205/02.03.01_60/en_31941205v020301p.pdf
#ETSI EN 319 411-1 V1.2.0 (2017-08) - https://www.etsi.org/deliver/etsi_EN/319400_319499/31941101/01.02.00_20/en_31941101v010200a.pdf
#ETSI TS 119 495   V1.4.1 (2019-11) - https://www.etsi.org/deliver/etsi_ts/119400_119499/119495/01.04.01_60/ts_119495v010401p.pdf
#ETSI TS 101 456   V1.4.3 (2007-05) - https://www.etsi.org/deliver/etsi_ts/101400_101499/101456/01.04.03_60/ts_101456v010403p.pdf

#VARIABLES - Defaults
  SSL_url_0                            = example.com
  SSL_url_1                            = secure.example.com
  SSL_organizationName_0               = Example Company Limited
  SSL_organizationName_1               = Công Ty Trách Nhiệm Hữu Hạn Example
  SSL_countryName                      = VN
  #SSL_countryName_1                    = CA
  SSL_stateOrProvinceName              = Hà Nội
  SSL_nCA                              = EXAMPLE
  SSL_nCAId                            = 12345678
  SSL_currency                         = VND
openssl_conf                           = RFC3739_init
#oid_section                            = RFC3739_OIDs
[RFC3739_init]
  oid_section                          = RFC3739_OIDs
[RFC3739_OIDs]
  #biometricInfo                        = 1.3.6.1.5.5.7.1.2  #id-pe-biometricInfo
  #qcStatements                         = 1.3.6.1.5.5.7.1.3  #id-pe-qcStatements
  #id-qcs                               = 1.3.6.1.5.5.7.11   #qcs
  #id-qcs-pkixQCSyntax-v1               = 1.3.6.1.5.5.7.11.1 #qcs-pkixQCSyntax-v1
  id-qcs-pkixQCSyntax-v2               = 1.3.6.1.5.5.7.11.2 #qcs-pkixQCSyntax-v2
  cabfOrganizationIdentifier           = 2.23.140.3.1       #cabforganization_identifier
  #qualified-certificate-policies      - ETSI TS 101 456
  #qualified-certificate-policies       = 0.4.0.1456         #id-etsi-qualified-certificate-policies
  qcp-public-with-sscd                 = 0.4.0.1456.1
  qcp-public                           = 0.4.0.1456.2
  #id-etsi-qcStatements                - ETSI EN 319 412-5
  #qc-profile                           = 0.4.0.1862         #etsi-qc-profile eIDAS PSD2
  #id-mod-qc-profile-2                  = 0.4.0.1862.0.2
  #id-etsi-qcStatements                 = 0.4.0.1862.1       #etsi-qcStatements
  qcs-qcCompliance                     = 0.4.0.1862.1.1     #qcCompliance
  qcs-qcLimitValue                     = 0.4.0.1862.1.2     #qcLimitValue
  qcs-qcRetentionPeriod                = 0.4.0.1862.1.3     #qcRetentionPeriod - int years
  qcs-QcSSCD                           = 0.4.0.1862.1.4     #qcSSCD            - Secure Signature Creation Device (SSCD)
  qcs-qcPDS                            = 0.4.0.1862.1.5     #qcPDS             - url
  qcs-qcCClegislation                  = 0.4.0.1862.1.7     #qcCClegislation
  qcs-qcType                           = 0.4.0.1862.1.6     #qcType
  qct-eSign                            = 0.4.0.1862.1.6.1
  qct-eSeal                            = 0.4.0.1862.1.6.2
  qct-web                              = 0.4.0.1862.1.6.3
  #other-certificate-policies          - ETSI EN 319 411-1
  #other-certificate-policies           = 0.4.0.2042.1       #id-etsi-other-certificate-policies
  ncp                                  = 0.4.0.2042.1.1     #normalized-certificate-policy
  ncpplus                              = 0.4.0.2042.1.2     #normalized-secure-certificate-policy
  lcp                                  = 0.4.0.2042.1.3     #lightweight-certificate-policy
  evcp                                 = 0.4.0.2042.1.4     #extended-validation-certificate-policy
  evcpplus                             = 0.4.0.2042.1.5     #extended-validation-secure-certificate-policy
  dvcp                                 = 0.4.0.2042.1.6     #domain-validation-certificate-policy
  ovcp                                 = 0.4.0.2042.1.7     #organization-validation-certificate-policy
  ivcp                                 = 0.4.0.2042.1.8     #individual-validation-certificate-policy
  #id-etsi-psd2                        - ETSI TS 119 495
  #etsi-psd2                            = 0.4.0.19495
  #etsi-psd2-roles                      = 0.4.0.19495.1
  id-psd2-role-psp-as                  = 0.4.0.19495.1.1    #psp-account-servicing
  id-psd2-role-psp-pi                  = 0.4.0.19495.1.2    #psp-payment-initiation
  id-psd2-role-psp-ai                  = 0.4.0.19495.1.3    #psp-account-information
  id-psd2-role-psp-ic                  = 0.4.0.19495.1.4    #psp-issuing-card-payment-instruction
  id-etsi-psd2-qcStatement             = 0.4.0.19495.2      #etsi-psd2-qcStatement, qcPDS2, qcs-qcPDS2
  #etsi-psd2-policy                     = 0.4.0.19495.3      #psd2-policy
  qcp-web-psd2                         = 0.4.0.19495.3.1    #qcp-w-psd2
  #qcs-policy-identifiers              - ETSI EN 319 412-2
  #id-etsi-qcs-policy-identifiers       = 0.4.0.194112.1     #qcs-policy-identifiers
  qcp-natural                          = 0.4.0.194112.1.0   #qcp-l      - natural person
  qcp-legal                            = 0.4.0.194112.1.1   #qcp-n      - legal person
  qcp-natural-qscd                     = 0.4.0.194112.1.2   #qcp-n-qscd - natural person seal creation device
  qcp-legal-qscd                       = 0.4.0.194112.1.3   #qcp-l-qscd - legal person seal creation device
  qcp-web                              = 0.4.0.194112.1.4   #qcp-w      - website
  #qcs-semantics-identifiers           - ETSI EN 319 412-1
  #id-etsi-qcs-semantics-identifiers    = 0.4.0.194121.1     #qcs-semantics-identifiers
  id-etsi-qcs-SemanticsId-Natural      = 0.4.0.194121.1.1   #qcs-SemanticsId-Natural, eSign
  id-etsi-qcs-SemanticsId-Legal        = 0.4.0.194121.1.2   #qcs-SemanticsId-Legal, eSeal
  id-etsi-qcs-SemanticsId-eIDASNatural = 0.4.0.194121.1.3   #qcs-SemanticsId-eIDASNatural, eSign
  id-etsi-qcs-SemanticsId-eIDASLegal   = 0.4.0.194121.1.4   #qcs-SemanticsId-eIDASLegal, eSeal

[req]
  distinguished_name = RFC3739_DNs
  x509_extensions    = RFC3739_ext
[RFC3739_DNs]
  description         = RFC3739
  description_default = RFC3739

[RFC3739_ext]
  certificatePolicies               = qcp-web,qcp-legal,qcp-legal-qscd,evcp,evcpplus,qcp-web-psd2,qcp-public
  qcStatements                      = ASN1:SEQ:qcStatements
  subjectDirectoryAttributes        = ASN1:SEQ:personalDataAttributes #id-pda
  biometricInfo                     = ASN1:SEQ:biometricSyntax
  cabfOrganizationIdentifier        = ASN1:SEQ:cabfOrganizationIdentifier

[cabfOrganizationIdentifier]
  scheme  = PRINTABLE:PSD
  country = PRINTABLE:${ENV::SSL_countryName}
  state   = IMP:0,UTF8:${ENV::SSL_stateOrProvinceName}
  nCAId   = UTF8:${ENV::SSL_nCA}-${ENV::SSL_nCAId}

[biometricSyntax]
  0.biometricData = SEQ:biometricData-0
  1.biometricData = SEQ:biometricData-1
[biometricData-0]
  typeOfBiometricData = INT:0 #picture INT:0, handwritten-signature INT:1, biometricDataOid
  hashAlgorithm = SEQWRAP,OID:SHA256
  biometricDataHash = OCT:38CF6A36FDE77FC193E224834AE353CEA31302D9B681FB39C11622D63A5ADB99
  sourceDataUri = IA5:https://${ENV::SSL_url_1}/ca/user/${biometricDataHash}.jpg #optional
[biometricData-1]
  typeOfBiometricData = INT:1
  hashAlgorithm = SEQWRAP,OID:SHA256
  biometricDataHash = OCT:38CF6A36FDE77FC193E224834AE353CEA31302D9B681FB39C11622D63A5ADB99
  sourceDataUri = IA5:https://${ENV::SSL_url_1}/ca/user/${biometricDataHash}.jpg #optional

[personalDataAttributes]
  dateOfBirth          = SEQ:pda-dateOfBirth
  placeOfBirth         = SEQ:pda-placeOfBirth
  gender               = SEQ:pda-gender
  CountryOfCitizenship = SEQ:pda-countryOfCitizenship #can be specified multiple times
  0.CountryOfResidence = SEQ:pda-countryOfResidence-0 #can be specified multiple times
  1.CountryOfResidence = SEQ:pda-countryOfResidence-1
[pda-dateOfBirth]
  oid   = OID:id-pda-dateOfBirth
  value = SETWRAP,GENTIME:19870716000000Z #GeneralizedTime - YYYYMMDDHHMMSS.SZ
[pda-placeOfBirth]
  oid   = OID:id-pda-placeOfBirth
  value = SETWRAP,UTF8:my hospital, address, province, CA #Should be DirectoryString = choice (3) = utf8
[pda-gender]
  oid   = OID:id-pda-gender
  value = SETWRAP,PRINTABLE:M #PrintableString - M,m,F,f
[pda-countryOfCitizenship]
  oid   = OID:id-pda-countryOfCitizenship
  value = SETWRAP,PRINTABLE:CA #PrintableString - ISO 3166 Country Code - 2 digits
[pda-countryOfResidence-0]
  oid   = OID:id-pda-countryOfResidence
  value = SETWRAP,PRINTABLE:${ENV::SSL_countryName} #PrintableString - ISO 3166 Country Code - 2 digits
[pda-countryOfResidence-1]
  oid   = OID:id-pda-countryOfResidence
  value = SETWRAP,PRINTABLE:CA #PrintableString - ISO 3166 Country Code - 2 digits

[qcStatements]
  qcpkixQCSyntax    = SEQ:qcs-qcpkixQCSyntax #SEQWRAP,OID:id-qcs-pkixQCSyntax-v2 #id-qcs-pkixQCSyntax-v1
  qcCompliance      = SEQWRAP,OID:qcs-qcCompliance
  qcLimitValue      = SEQ:qcs-qcLimitValue
  qcRetentionPeriod = SEQ:qcs-qcRetentionPeriod
  qcSSCD            = SEQWRAP,OID:qcs-QcSSCD
  qcPDS             = SEQ:qcs-qcPDS
  qcType            = SEQ:qcs-qcType
  qcCClegislation   = SEQ:qcs-qcCClegislation
  qcPDS2            = SEQ:qcs-qcPDS2
[qcs-qcpkixQCSyntax]
  statementId       = OID:id-qcs-pkixQCSyntax-v2 #id-qcs-pkixQCSyntax-v1
  statementInfo     = SEQWRAP,OID:id-etsi-qcs-SemanticsId-Legal #can have multiple
[qcs-qcLimitValue]
  statementId       = OID:qcs-qcLimitValue
  monetaryValue     = SEQ:qcLimitValue
[qcLimitValue]
  limitCurrency     = PRINTABLE:${ENV::SSL_currency} #or INT:(0-999) ISO 4217
  limitAmount       = INT:1000000
  limitExponent     = INT:10 #value = amount * 10^exponent
[qcs-qcRetentionPeriod]
  statementId       = OID:qcs-qcRetentionPeriod
  retentionYears    = INT:15
[qcs-qcPDS]
  statementId       = OID:qcs-qcPDS
  qcPDS             = SEQ:qcPDS
[qcPDS]
  0.PDSLocation     = SEQ:PDSLocation-0
  1.PDSLocation     = SEQ:PDSLocation-1
  2.PDSLocation     = SEQ:PDSLocation-2
  3.PDSLocation     = SEQ:PDSLocation-3
[PDSLocation-0]
  url               = IA5:https://${ENV::SSL_url_0}/ca/pds
  lang              = PRINTABLE:en
[PDSLocation-1]
  url               = IA5:https://${ENV::SSL_url_0}/ca/pds
  lang              = PRINTABLE:vi
[PDSLocation-2]
  url               = IA5:https://${ENV::SSL_url_1}/ca/pds
  lang              = PRINTABLE:en
[PDSLocation-3]
  url               = IA5:https://${ENV::SSL_url_1}/ca/pds
  lang              = PRINTABLE:vi
[qcs-qcType]
  statementId       = OID:qcs-qcType
  typeName          = SEQ:qcType
[qcType]
  0.qcType          = OID:qct-eSign
  1.qcType          = OID:qct-eSeal
  2.qcType          = OID:qct-web
[qcs-qcCClegislation]
  statementId       = OID:qcs-qcCClegislation
  countryName       = SEQ:qcCClegislation
[qcCClegislation]
  0.countryName     = PRINTABLE:${ENV::SSL_countryName}
  1.countryName     = PRINTABLE:CA
[qcs-qcPDS2]
  statementId       = OID:id-etsi-psd2-qcStatement
  statementInfo     = SEQ:qcPDS2
[qcPDS2]
  rolesOfPSP        = SEQ:PSProles
  nCAName           = UTF8:${ENV::SSL_organizationName_0} / ${ENV::SSL_organizationName_1}
  nCAId             = UTF8:PSD${ENV::SSL_countryName}-${ENV::SSL_nCA}-${ENV::SSL_nCAId} #VN-TWOEIGHT-1234567890
[PSProles]
  0.PSProle         = SEQ:PSProle-0
  1.PSProle         = SEQ:PSProle-1
  2.PSProle         = SEQ:PSProle-2
  3.PSProle         = SEQ:PSProle-3
[PSProle-0]
  roleOfPspOid      = OID:id-psd2-role-psp-as
  roleOfPspName     = UTF8:PSP_AS
[PSProle-1]
  roleOfPspOid      = OID:id-psd2-role-psp-pi
  roleOfPspName     = UTF8:PSP_PI
[PSProle-2]
  roleOfPspOid      = OID:id-psd2-role-psp-ai
  roleOfPspName     = UTF8:PSP_AI
[PSProle-3]
  roleOfPspOid      = OID:id-psd2-role-psp-ic
  roleOfPspName     = UTF8:PSP_IC

我会留意评论,如果有任何不正确的地方,我会进行编辑。