Java 将PEM证书解析为JSON

Java 将PEM证书解析为JSON,java,bash,openssl,ssl-certificate,pem,Java,Bash,Openssl,Ssl Certificate,Pem,我有一个PEM证书,我正在使用openssl查看它的内容。是否可以将输出解析为JSON格式?也许有Java库或Bash脚本可以做到这一点 命令:$opensslx509-in sample.cer-noout-text 输出: Certificate: Data: Version: 3 (0x2) Serial Number: af:69:46:11:10:bd:82:88 Signature Algorithm:

我有一个PEM证书,我正在使用
openssl
查看它的内容。是否可以将输出解析为JSON格式?也许有Java库或Bash脚本可以做到这一点

命令:
$opensslx509-in sample.cer-noout-text

输出:

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            af:69:46:11:10:bd:82:88
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=US, ST=Texas, L=Plano, O=2xoffice, OU=Architecture, CN=Joshua Davies/emailAddress=joshua.davies.tx@gmail.com
        Validity
            Not Before: May 21 21:49:10 2014 GMT
            Not After : Jun 20 21:49:10 2014 GMT
        Subject: C=US, ST=Texas, L=Plano, O=2xoffice, OU=Architecture, CN=Joshua Davies/emailAddress=joshua.davies.tx@gmail.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (512 bit)
                Modulus (512 bit):
                    00:b7:38:0d:e0:ab:37:18:a7:26:95:9d:9e:6f:a2:
                    69:b1:b9:ee:b3:7f:29:04:fb:f0:94:b3:d0:d5:55:
                    c0:d8:6b:14:7f:94:13:3c:d9:a2:61:bf:ba:3f:0a:
                    44:37:dc:18:b5:23:c7:ee:96:2d:7c:d8:92:04:48:
                    74:f8:c6:46:a5
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                1A:A5:C9:C8:36:EA:7D:FA:B4:DF:A4:9C:11:F9:C1:BE:78:C4:42:DD
            X509v3 Authority Key Identifier: 
                keyid:1A:A5:C9:C8:36:EA:7D:FA:B4:DF:A4:9C:11:F9:C1:BE:78:C4:42:DD
                DirName:/C=US/ST=Texas/L=Plano/O=2xoffice/OU=Architecture/CN=Joshua Davies/emailAddress=joshua.davies.tx@gmail.com
                serial:AF:69:46:11:10:BD:82:88

            X509v3 Basic Constraints: 
                CA:TRUE
    Signature Algorithm: sha1WithRSAEncryption
        56:32:44:76:86:8c:08:92:74:71:0e:ac:a6:7d:ba:1d:7c:d3:
        b6:74:ef:27:7a:5e:53:21:fc:8e:eb:26:58:e0:6e:4f:5c:01:
        f1:40:ca:0a:e9:d2:0e:00:60:ae:1f:f6:a5:a4:4c:47:fb:e0:
        68:7f:25:63:ab:60:38:0f:74:94

我能够构建一个Python脚本来完成您所需要的功能。此脚本接受一个参数,
,并返回包含此内容的JSON对象

$ ./pem2json.py <PEM FILE>
代码 调试输出 工具书类

我一直在寻找这一点,并在服务器上运行了大量PHP脚本

@slm的答案可能很好,但这里有一个内置的PHP函数,它可以做您想要的事情


这是我自己的python脚本(源自上面的脚本)

它还可以接受具有多个证书的PEM

#!/usr/bin/env python3

import os, sys
import tempfile
import json

import pem
import ssl

def main():
    cert_file_name = sys.argv[1]
    try:
        pems = pem.parse_file(cert_file_name)
    except Exception as e:
        print(f"Error decoding pem: {e}\n")
        sys.exit(1)

    res = []
    for p in pems:
        f = tempfile.NamedTemporaryFile(mode='w', delete=False)
        f.write(p.as_text())
        f.close()

        try:
            cert = ssl._ssl._test_decode_cert(f.name)
            # remap array mess in subject and issuer into dicts
            for item in ['subject', 'issuer']:
                if item in cert:
                    item_dict = {}
                    for s in cert[item]:
                        for i in s:
                            if i[0] not in item_dict:
                                item_dict[i[0]] = []
                            item_dict[i[0]].append(i[1])
                    # collapse single item arrays into scalars
                    for k,v in item_dict.items():
                        if len(v) == 1:
                            item_dict[k] = v[0]
                    cert[item] = item_dict
            # remap array mess in subjectAltName into a dict
            if 'subjectAltName' in cert:
                item = 'subjectAltName'
                san_dict = {}
                for i in cert[item]:
                    if i[0] not in san_dict:
                        san_dict[i[0]] = []
                    san_dict[i[0]].append(i[1])
                cert[item] = san_dict

            res.append(cert)
        except Exception as e:
            print(f"Error decoding certificate: {e}\n")

        os.unlink(f.name)


    print(json.dumps(res))

if __name__ == "__main__":
    main()

因为我面临一个模拟问题,所以我写了一个简单(适合我的需要)的bash脚本。此脚本从stdin获取x509格式化证书,提取所需字段并创建简单的json输出

#!/bin/bash
IFS=''

CERT=$(timeout 3s cat)
# TODO: INPUT Validierung:
#          Input überhaupt vorhanden?
#          Input valides x509 Format?

if [ -z "$CERT" ]; then
    echo "NO STDIN Input -> EXIT"
    exit 12
fi

getCertSubject() {
  echo $CERT | awk 'BEGIN{FS="Subject: "} NF==2{print $2}'
}
getCertSignatureAlgorithm() {
  echo $CERT | awk 'BEGIN{FS="Signature Algorithm: "} NF==2{print $2}'|head -n 1
}
getCertIssuer() {
  echo $CERT | awk 'BEGIN{FS="Issuer: "} NF==2{print $2}'
}
getCertNotBefore() {
  echo $CERT | awk 'BEGIN{FS="Not Before: "} NF==2{print $2}'
}
getCertNotAfter() {
  echo $CERT | awk 'BEGIN{FS="Not After : "} NF==2{print $2}'
}
getCertIssuerURL() {
  echo $CERT | awk 'BEGIN{FS="CA Issuers - URI:"} NF==2{print $2}'
}
getCertDNS() {
  echo $CERT | sed -n '/Subject Alternative Name:/{n;p;}' | xargs | sed "s/DNS://g" | sed "s/,//g"
}
getCertSerialNumber() {
  echo $CERT | sed -n '/Serial Number:/{n;p;}' | xargs
}
getCertSubjectKeyIdentifier() {
  echo $CERT | sed -n '/Subject Key Identifier:/{n;p;}' | xargs
}
getCertAuthorityKeyIdentifier() {
  echo $CERT | sed -n '/Authority Key Identifier:/{n;p;}' | xargs
}
getCommonName(){
    echo $1 | awk 'BEGIN{FS="(^| )CN( )*="} NF==2{print $2}' | awk -F, '{print $1}'| xargs
}
getOrganisation(){
    echo $1 | awk 'BEGIN{FS="(^| )O( )*="} NF==2{print $2}' | awk -F, '{print $1}'| xargs
}
getCountry(){
    echo $1 | awk 'BEGIN{FS="(^| )C( )*="} NF==2{print $2}' | awk -F, '{print $1}'| xargs
}
getDNSArray(){
    echo $1 | sed 's/ /\", \"/g;s/^/\"/;s/$/\"/'
}

SUBJECT=$(getCertSubject)
ISSUER=$(getCertIssuer)

read -r -d '' JSON << EOM
{
  "label": "$(getCommonName $SUBJECT)",
  "node": "$(hostname)",
  "date": "$(date)",
  "subject": {
    "raw": "$SUBJECT",
    "common_name": "$(getCommonName $SUBJECT)",
    "country": "$(getCountry $SUBJECT)",
    "organization": "$(getOrganisation $SUBJECT)",
    "names": [
       $(getDNSArray $(getCertDNS))
    ]
  },
  "issuer": {
    "raw": "$ISSUER",
    "common_name": "$(getCommonName $ISSUER)",
    "country": "$(getCountry $ISSUER)",
    "organization": "$(getOrganisation $ISSUER)",
    "url": "$(getCertIssuerURL)"
  },
  "serial_number": "$(getCertSerialNumber)",
  "sans": [
    $(getDNSArray $(getCertDNS))
  ],
  "not_before": "$(getCertNotBefore)",
  "not_after": "$(getCertNotAfter)",
  "sigalg": "$(getCertSignatureAlgorithm)",
  "authority_key_id": "$(getCertAuthorityKeyIdentifier)",
  "subject_key_id": "$(getCertSubjectKeyIdentifier)"
}
EOM

echo "$JSON"
#/bin/bash
如果=“”
证书=$(超时3s cat)
#TODO:输入有效中断:
#输入法?
#输入valides x509格式?
如果[-z“$CERT”];然后
回显“无标准输入->退出”
12号出口
fi
getCertSubject(){
echo$CERT | awk'BEGIN{FS=“Subject:”}NF==2{print$2}'
}
getCertSignatureAlgorithm(){
echo$CERT | awk'BEGIN{FS=“签名算法:”}NF==2{print$2}'| head-n1
}
getCertIssuer(){
echo$CERT | awk'BEGIN{FS=“Issuer:”}NF==2{print$2}'
}
getCertNotBefore(){
echo$CERT | awk'BEGIN{FS=“notbefore:”}NF==2{print$2}”
}
getCertNotAfter(){
echo$CERT | awk'BEGIN{FS=“notafter:”}NF==2{print$2}”
}
getCertissueUrl(){
echo$CERT | awk'BEGIN{FS=“CA发行人-URI:”}NF==2{print$2}'
}
getCertDNS(){
echo$CERT | sed-n'/主题备选名称://{n;p;}'| xargs | sed“s/DNS://g”| sed“s/,//g”
}
getCertSerialNumber(){
echo$CERT | sed-n'/序列号:/{n;p;}'| xargs
}
getCertSubjectKeyIdentifier(){
echo$CERT | sed-n'/主题密钥标识符:/{n;p;}'| xargs
}
getCertAuthorityKeyIdentifier(){
echo$CERT | sed-n'/权限密钥标识符:/{n;p;}'| xargs
}
getCommonName(){
echo$1 | awk'BEGIN{FS=“(^ |)CN()*=”}NF==2{print$2}'| awk-F,{print$1}'| xargs
}
GetOrganization(){
echo$1 | awk'BEGIN{FS=“(^ |)O()*=”}NF==2{print$2}'| awk-F,{print$1}'| xargs
}
getCountry(){
echo$1 | awk'BEGIN{FS=“(^ |)C()*=”}NF==2{print$2}'| awk-F,{print$1}'| xargs
}
getDNSArray(){
echo$1|sed's//\,\“/g;s/^/\”/;s/$/\”/'
}
主题=$(getCertSubject)
发卡机构=$(getCertIssuer)

read-r-d''JSON的用途是什么?你的目标是什么?在bash中无法做到这一点。您必须使用不同的实用程序。
$ ./pem2json.py 2048b-dsa-example-cert.pem -d
Python 2.7.5 (default, Jul 13 2018, 13:06:57)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux2

cli arg1: 2048b-dsa-example-cert.pem

{'issuer': ((('countryName', u'JP'),),
            (('stateOrProvinceName', u'Tokyo'),),
            (('localityName', u'Chuo-ku'),),
            (('organizationName', u'Frank4DD'),),
            (('organizationalUnitName', u'WebCert Support'),),
            (('commonName', u'Frank4DD Web CA'),),
            (('emailAddress', u'support@frank4dd.com'),)),
 'notAfter': 'Aug 21 07:27:22 2017 GMT',
 'notBefore': u'Aug 22 07:27:22 2012 GMT',
 'serialNumber': u'0E02',
 'subject': ((('countryName', u'JP'),),
             (('stateOrProvinceName', u'Tokyo'),),
             (('organizationName', u'Frank4DD'),),
             (('commonName', u'www.example.com'),)),
 'version': 1L}
{"notBefore": "Aug 22 07:27:22 2012 GMT", "serialNumber": "0E02", "notAfter": "Aug 21 07:27:22 2017 GMT", "version": 1, "subject": [[["countryName", "JP"]], [["stateOrProvinceName", "Tokyo"]], [["organizationName", "Frank4DD"]], [["commonName", "www.example.com"]]], "issuer": [[["countryName", "JP"]], [["stateOrProvinceName", "Tokyo"]], [["localityName", "Chuo-ku"]], [["organizationName", "Frank4DD"]], [["organizationalUnitName", "WebCert Support"]], [["commonName", "Frank4DD Web CA"]], [["emailAddress", "support@frank4dd.com"]]]}
#!/usr/bin/env python3

import os, sys
import tempfile
import json

import pem
import ssl

def main():
    cert_file_name = sys.argv[1]
    try:
        pems = pem.parse_file(cert_file_name)
    except Exception as e:
        print(f"Error decoding pem: {e}\n")
        sys.exit(1)

    res = []
    for p in pems:
        f = tempfile.NamedTemporaryFile(mode='w', delete=False)
        f.write(p.as_text())
        f.close()

        try:
            cert = ssl._ssl._test_decode_cert(f.name)
            # remap array mess in subject and issuer into dicts
            for item in ['subject', 'issuer']:
                if item in cert:
                    item_dict = {}
                    for s in cert[item]:
                        for i in s:
                            if i[0] not in item_dict:
                                item_dict[i[0]] = []
                            item_dict[i[0]].append(i[1])
                    # collapse single item arrays into scalars
                    for k,v in item_dict.items():
                        if len(v) == 1:
                            item_dict[k] = v[0]
                    cert[item] = item_dict
            # remap array mess in subjectAltName into a dict
            if 'subjectAltName' in cert:
                item = 'subjectAltName'
                san_dict = {}
                for i in cert[item]:
                    if i[0] not in san_dict:
                        san_dict[i[0]] = []
                    san_dict[i[0]].append(i[1])
                cert[item] = san_dict

            res.append(cert)
        except Exception as e:
            print(f"Error decoding certificate: {e}\n")

        os.unlink(f.name)


    print(json.dumps(res))

if __name__ == "__main__":
    main()
#!/bin/bash
IFS=''

CERT=$(timeout 3s cat)
# TODO: INPUT Validierung:
#          Input überhaupt vorhanden?
#          Input valides x509 Format?

if [ -z "$CERT" ]; then
    echo "NO STDIN Input -> EXIT"
    exit 12
fi

getCertSubject() {
  echo $CERT | awk 'BEGIN{FS="Subject: "} NF==2{print $2}'
}
getCertSignatureAlgorithm() {
  echo $CERT | awk 'BEGIN{FS="Signature Algorithm: "} NF==2{print $2}'|head -n 1
}
getCertIssuer() {
  echo $CERT | awk 'BEGIN{FS="Issuer: "} NF==2{print $2}'
}
getCertNotBefore() {
  echo $CERT | awk 'BEGIN{FS="Not Before: "} NF==2{print $2}'
}
getCertNotAfter() {
  echo $CERT | awk 'BEGIN{FS="Not After : "} NF==2{print $2}'
}
getCertIssuerURL() {
  echo $CERT | awk 'BEGIN{FS="CA Issuers - URI:"} NF==2{print $2}'
}
getCertDNS() {
  echo $CERT | sed -n '/Subject Alternative Name:/{n;p;}' | xargs | sed "s/DNS://g" | sed "s/,//g"
}
getCertSerialNumber() {
  echo $CERT | sed -n '/Serial Number:/{n;p;}' | xargs
}
getCertSubjectKeyIdentifier() {
  echo $CERT | sed -n '/Subject Key Identifier:/{n;p;}' | xargs
}
getCertAuthorityKeyIdentifier() {
  echo $CERT | sed -n '/Authority Key Identifier:/{n;p;}' | xargs
}
getCommonName(){
    echo $1 | awk 'BEGIN{FS="(^| )CN( )*="} NF==2{print $2}' | awk -F, '{print $1}'| xargs
}
getOrganisation(){
    echo $1 | awk 'BEGIN{FS="(^| )O( )*="} NF==2{print $2}' | awk -F, '{print $1}'| xargs
}
getCountry(){
    echo $1 | awk 'BEGIN{FS="(^| )C( )*="} NF==2{print $2}' | awk -F, '{print $1}'| xargs
}
getDNSArray(){
    echo $1 | sed 's/ /\", \"/g;s/^/\"/;s/$/\"/'
}

SUBJECT=$(getCertSubject)
ISSUER=$(getCertIssuer)

read -r -d '' JSON << EOM
{
  "label": "$(getCommonName $SUBJECT)",
  "node": "$(hostname)",
  "date": "$(date)",
  "subject": {
    "raw": "$SUBJECT",
    "common_name": "$(getCommonName $SUBJECT)",
    "country": "$(getCountry $SUBJECT)",
    "organization": "$(getOrganisation $SUBJECT)",
    "names": [
       $(getDNSArray $(getCertDNS))
    ]
  },
  "issuer": {
    "raw": "$ISSUER",
    "common_name": "$(getCommonName $ISSUER)",
    "country": "$(getCountry $ISSUER)",
    "organization": "$(getOrganisation $ISSUER)",
    "url": "$(getCertIssuerURL)"
  },
  "serial_number": "$(getCertSerialNumber)",
  "sans": [
    $(getDNSArray $(getCertDNS))
  ],
  "not_before": "$(getCertNotBefore)",
  "not_after": "$(getCertNotAfter)",
  "sigalg": "$(getCertSignatureAlgorithm)",
  "authority_key_id": "$(getCertAuthorityKeyIdentifier)",
  "subject_key_id": "$(getCertSubjectKeyIdentifier)"
}
EOM

echo "$JSON"