admin管理员组

文章数量:1651364

QSslCertificate支持x509证书信息的解析

证书信息接口

函数功能
QByteArray version() const版本
QByteArray serialNumber() const;序列号
QString issuerDisplayName() const;颁发者common name(CN)
QString subjectDisplayName() const;使用者common name(CN)
QDateTime effectiveDate() const;生效日期
QDateTime expiryDate() const;截止日期
QSslKey publicKey() const;公钥
QList<QSslCertificateExtension> extensions() const;扩展项

获取加密算法类型

    QSslKey pubKey = m_pX509->publicKey();
    QString pubAlg;
    //算法类型
    switch (pubKey.algorithm()) {
    case QSsl::Opaque:
        pubAlg = "Opaque";
        break;
    case QSsl::Rsa:
        pubAlg = "RSA";
        break;
    case QSsl::Dsa:
        pubAlg = "DSA";
        break;
    case QSsl::Ec:
        pubAlg = "ECC";
        break;
    default:
        break;
    }
    //密钥长度
    int pubLen = pubKey.length();
    QString alg = QString("%1(%2 bits)").arg(pubAlg).arg(pubLen);
    qDebug() << __FUNCTION__ << "song" << "pub alg" << alg;
MainWindow::MainWindow song pub alg "RSA(2048 bits)"

获取公钥值

QByteArray pubDer = pubKey.toDer();
//转成16进制
QByteArray pubVal = pubDer.toHex();
qDebug() << __FUNCTION__ << "song" << "pub val" << pubVal
MainWindow::MainWindow song pub val "30820122300d06092a864886f70d01010105000382010f003082010a0282010100c1a9b0ae471ad257eb1d151f6e5cb2e4f80b20dbea00df29ffa46b89264b9f232fec57b08ab846402a7ebcdc5a45974fad410ebc20864b0c5d552147e2313c57a7ec9947eb470d72d7c8165475efd345110f4bce607a465c2874ae8e1bbed870667ba8934928d2a3769455de7c27f20ff7980cad86dac6aefd9ff0d981329a97e321ee049296e47811e5c4100e10317a4a97a0ebc79bc4da8937a9c337d756b17f52c7d9260ad6af3816b16dfb7379b168790390eb887b8c48919851a5079486a57846798f589be93559a7f17b57310a90cf24ce0d24e792b26ae9e696370ab87c872f74d25ce84b0a5f6618a74186cf26a6088ea549179253b391a5cf53b0310203010001"

QSslKey没有提供接口获取公钥具体值,如RSA的模(n)和指数(e),SM2的X和Y

我们是可以从上述的公钥值中找出n和e的,这里需要了解RSA公钥的TLV分段,可以看这篇介绍https://wenku.baidu/view/9d303b14f011f18583d049649b6648d7c1c708fd.html

按照TLV分段组成,模数n从010100后开始,到0203前结束

c1a9b0ae471ad257eb1d151f6e5cb2e4f80b20dbea00df29ffa46b89264b9f232fec57b08ab846402a7ebcdc5a45974fad410ebc20864b0c5d552147e2313c57a7ec9947eb470d72d7c8165475efd345110f4bce607a465c2874ae8e1bbed870667ba8934928d2a3769455de7c27f20ff7980cad86dac6aefd9ff0d981329a97e321ee049296e47811e5c4100e10317a4a97a0ebc79bc4da8937a9c337d756b17f52c7d9260ad6af3816b16dfb7379b168790390eb887b8c48919851a5079486a57846798f589be93559a7f17b57310a90cf24ce0d24e792b26ae9e696370ab87c872f74d25ce84b0a5f6618a74186cf26a6088ea549179253b391a5cf53b031

指数e从0203后到结尾

010001

把上述公钥转成PEM格式,使用第三方工具解析对比可以看到是正确的

//生成pem格式
pubKey.toPem()

//结果
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwamwrkca0lfrHRUfblyy
5PgLINvqAN8p/6RriSZLnyMv7FewirhGQCp+vNxaRZdPrUEOvCCGSwxdVSFH4jE8
V6fsmUfrRw1y18gWVHXv00URD0vOYHpGXCh0ro4bvthwZnuok0ko0qN2lFXefCfy
D/eYDK2G2sau/Z/w2YEympfjIe4EkpbkeBHlxBAOEDF6Speg68ebxNqJN6nDN9dW
sX9Sx9kmCtavOBaxbftzebFoeQOQ64h7jEiRmFGlB5SGpXhGeY9Ym+k1Wafxe1cx
CpDPJM4NJOeSsmrp5pY3Crh8hy900lzoSwpfZhinQYbPJqYIjqVJF5JTs5Glz1Ow
MQIDAQAB
-----END PUBLIC KEY-----

获取证书指纹

//sha1指纹    
QByteArray sha1FP = m_pX509->digest(QCryptographicHash::Sha1).toHex();
//sha256指纹
QByteArray sha256FP = m_pX509->digest(QCryptographicHash::Sha256).toHex();

获取Subject信息

QSslCertificate没有提供完整Subject字段信息获取,只能获取单个DN中的某个字段

QStringList nameList = m_pX509->subjectInfo(QSslCertificate::CommonName);

Issuer信息一样

获取使用者可选名称

该字段是扩展项中的内容,但使用extensions取到的值不全,使用以下接口可获取

QMultiMap<QSsl::AlternativeNameEntryType, QString> subjectAlternativeNames() const;
QMultiMap<QSsl::AlternativeNameEntryType, QString> alterNameMap = m_pX509->subjectAlternativeNames();
QStringList alterDnsNameList = alterNameMap.values(QSsl::DnsEntry);
foreach (auto dnsName, alterDnsNameList) {
    qDebug() << __FUNCTION__ << "song" << "dns name" << dnsName;
}

扩展项

QList<QSslCertificateExtension> extList = m_pX509->extensions();
foreach (auto &ext, extList) {
    qDebug() << __FUNCTION__ << "song" << "ext oid" << ext.oid() << ext.name() << ext.value();
}
MainWindow::MainWindow song ext oid "2.5.29.15" "keyUsage" QVariant(QVariantList, (QVariant(QString, "Digital Signature"), QVariant(QString, "Key Encipherment"))) 

MainWindow::MainWindow song ext oid "1.3.6.1.5.5.7.1.1" "authorityInfoAccess" QVariant(QVariantMap, QMap(("OCSP", QVariant(QString, "http://ocsp2.globalsign/gsorganizationvalsha2g2"))("caIssuers", QVariant(QString, "http://secure.globalsign/cacert/gsorganizationvalsha2g2r1.crt")))) 

MainWindow::MainWindow song ext oid "2.5.29.32" "certificatePolicies" QVariant(QByteArray, "Policy: 1.3.6.1.4.1.4146.1.20\n  CPS: https://www.globalsign/repository/\nPolicy: 2.23.140.1.2.2\n") 

MainWindow::MainWindow song ext oid "2.5.29.19" "basicConstraints" QVariant(QVariantMap, QMap(("ca", QVariant(bool, false)))) 

MainWindow::MainWindow song ext oid "2.5.29.31" "crlDistributionPoints" QVariant(QByteArray, "\nFull Name:\n  URI:http://crl.globalsign/gs/gsorganizationvalsha2g2.crl\n") 

MainWindow::MainWindow song ext oid "2.5.29.17" "subjectAltName" QVariant(QVariantMap, QMap(("DNS", QVariant(QString, "update.pan.baidu")))) 

MainWindow::MainWindow song ext oid "2.5.29.37" "extendedKeyUsage" QVariant(QVariantList, (QVariant(QString, "TLS Web Server Authentication"), QVariant(QString, "TLS Web Client Authentication"))) 

MainWindow::MainWindow song ext oid "2.5.29.35" "authorityKeyIdentifier" QVariant(QVariantMap, QMap(("keyid", QVariant(QByteArray, "96de61f1bd1c1629531cc0cc7d3b830040e61a7c")))) 

MainWindow::MainWindow song ext oid "2.5.29.14" "subjectKeyIdentifier" QVariant(QString, "9E:C9:79:D7:E9:5B:AB:8A:16:CC:32:8E:C6:99:E6:9F:20:42:35:87") 

MainWindow::MainWindow song ext oid "1.3.6.1.4.1.11129.2.4.2" "ct_precert_scts" QVariant(QByteArray, "Signed Certificate Timestamp:\n    Version   : v1 (0x0)\n    Log ID    : 5C:DC:43:92:FE:E6:AB:45:44:B1:5E:9A:D4:56:E6:10:\n                37:FB:D5:FA:47:DC:A1:73:94:B2:5E:E6:F6:C7:0E:CA\n    Timestamp : Apr  2 07:05:11.098 2020 GMT\n    Extensions: none\n    Signature : ecdsa-with-SHA256\n                30:45:02:20:69:86:68:31:21:B3:59:5D:A3:D6:89:4A:\n                97:45:66:0B:69:14:93:DF:C2:9E:72:87:A4:28:8A:1F:\n                E5:F5:E6:B2:02:21:00:C9:19:B4:5F:17:C8:A0:AE:FE:\n                76:65:97:57:BD:BC:89:4A:6D:6F:11:AD:4A:FF:EF:81:\n                E9:99:27:15:45:1B:01\nSigned Certificate Timestamp:\n    Version   : v1 (0x0)\n    Log ID    : 6F:53:76:AC:31:F0:31:19:D8:99:00:A4:51:15:FF:77:\n                15:1C:11:D9:02:C1:00:29:06:8D:B2:08:9A:37:D9:13\n    Timestamp : Apr  2 07:05:11.140 2020 GMT\n    Extensions: none\n    Signature : ecdsa-with-SHA256\n                30:45:02:20:54:45:6C:30:4E:05:D9:FB:D2:15:DE:68:\n                66:13:41:0E:CD:B8:3D:D3:50:CB:46:CC:DB:2C:8A:5A:\n                7C:36:3F:5E:02:21:00:BB:2F:10:6A:9B:05:5A:E9:1B:\n                18:4A:A1:35:65:CF:BF:86:5A:89:BC:4A:B7:D4:78:77:\n                27:E3:EF:43:9F:BC:46\nSigned Certificate Timestamp:\n    Version   : v1 (0x0)\n    Log ID    : F6:5C:94:2F:D1:77:30:22:14:54:18:08:30:94:56:8E:\n                E3:4D:13:19:33:BF:DF:0C:2F:20:0B:CC:4E:F1:64:E3\n    Timestamp : Apr  2 07:05:11.083 2020 GMT\n    Extensions: none\n    Signature : ecdsa-with-SHA256\n                30:45:02:20:45:05:83:F1:28:47:61:95:FE:9B:A9:BC:\n                31:41:8E:ED:B2:48:1D:A0:5B:A5:3F:13:E6:76:BC:D2:\n                E6:D3:69:3F:02:21:00:A9:CA:AB:0C:DC:87:DF:25:20:\n                D4:18:CC:B0:15:E7:6F:82:F0:65:D9:3D:71:59:35:F8:\n                5F:A4:CE:2D:43:AC:5B") 

上面的例子使用的是百度的证书

-----BEGIN CERTIFICATE-----
MIIKLjCCCRagAwIBAgIMclh4Nm6fVugdQYhIMA0GCSqGSIb3DQEBCwUAMGYxCzAJ
BgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTwwOgYDVQQDEzNH
bG9iYWxTaWduIE9yZ2FuaXphdGlvbiBWYWxpZGF0aW9uIENBIC0gU0hBMjU2IC0g
RzIwHhcNMjAwNDAyMDcwNDU4WhcNMjEwNzI2MDUzMTAyWjCBpzELMAkGA1UEBhMC
Q04xEDAOBgNVBAgTB2JlaWppbmcxEDAOBgNVBAcTB2JlaWppbmcxJTAjBgNVBAsT
HHNlcnZpY2Ugb3BlcmF0aW9uIGRlcGFydG1lbnQxOTA3BgNVBAoTMEJlaWppbmcg
QmFpZHUgTmV0Y29tIFNjaWVuY2UgVGVjaG5vbG9neSBDby4sIEx0ZDESMBAGA1UE
AxMJYmFpZHUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwamw
rkca0lfrHRUfblyy5PgLINvqAN8p/6RriSZLnyMv7FewirhGQCp+vNxaRZdPrUEO
vCCGSwxdVSFH4jE8V6fsmUfrRw1y18gWVHXv00URD0vOYHpGXCh0ro4bvthwZnuo
k0ko0qN2lFXefCfyD/eYDK2G2sau/Z/w2YEympfjIe4EkpbkeBHlxBAOEDF6Speg
68ebxNqJN6nDN9dWsX9Sx9kmCtavOBaxbftzebFoeQOQ64h7jEiRmFGlB5SGpXhG
eY9Ym+k1Wafxe1cxCpDPJM4NJOeSsmrp5pY3Crh8hy900lzoSwpfZhinQYbPJqYI
jqVJF5JTs5Glz1OwMQIDAQABo4IGmDCCBpQwDgYDVR0PAQH/BAQDAgWgMIGgBggr
BgEFBQcBAQSBkzCBkDBNBggrBgEFBQcwAoZBaHR0cDovL3NlY3VyZS5nbG9iYWxz
aWduLmNvbS9jYWNlcnQvZ3Nvcmdhbml6YXRpb252YWxzaGEyZzJyMS5jcnQwPwYI
KwYBBQUHMAGGM2h0dHA6Ly9vY3NwMi5nbG9iYWxzaWduLmNvbS9nc29yZ2FuaXph
dGlvbnZhbHNoYTJnMjBWBgNVHSAETzBNMEEGCSsGAQQBoDIBFDA0MDIGCCsGAQUF
BwIBFiZodHRwczovL3d3dy5nbG9iYWxzaWduLmNvbS9yZXBvc2l0b3J5LzAIBgZn
gQwBAgIwCQYDVR0TBAIwADBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmds
b2JhbHNpZ24uY29tL2dzL2dzb3JnYW5pemF0aW9udmFsc2hhMmcyLmNybDCCA04G
A1UdEQSCA0UwggNBggliYWlkdS5jb22CDGJhaWZ1YmFvLmNvbYIMd3d3LmJhaWR1
LmNughB3d3cuYmFpZHUuY29tLmNugg9tY3QueS5udW9taS5jb22CC2Fwb2xsby5h
dXRvggZkd3ouY26CCyouYmFpZHUuY29tgg4qLmJhaWZ1YmFvLmNvbYIRKi5iYWlk
dXN0YXRpYy5jb22CDiouYmRzdGF0aWMuY29tggsqLmJkaW1nLmNvbYIMKi5oYW8x
MjMuY29tggsqLm51b21pLmNvbYINKi5jaHVhbmtlLmNvbYINKi50cnVzdGdvLmNv
bYIPKi5iY2UuYmFpZHUuY29tghAqLmV5dW4uYmFpZHUuY29tgg8qLm1hcC5iYWlk
dS5jb22CDyoubWJkLmJhaWR1LmNvbYIRKi5mYW55aS5iYWlkdS5jb22CDiouYmFp
ZHViY2UuY29tggwqLm1pcGNkbi5jb22CECoubmV3cy5iYWlkdS5jb22CDiouYmFp
ZHVwY3MuY29tggwqLmFpcGFnZS5jb22CCyouYWlwYWdlLmNugg0qLmJjZWhvc3Qu
Y29tghAqLnNhZmUuYmFpZHUuY29tgg4qLmltLmJhaWR1LmNvbYISKi5iYWlkdWNv
bnRlbnQuY29tggsqLmRsbmVsLmNvbYILKi5kbG5lbC5vcmeCEiouZHVlcm9zLmJh
aWR1LmNvbYIOKi5zdS5iYWlkdS5jb22CCCouOTEuY29tghIqLmhhbzEyMy5iYWlk
dS5jb22CDSouYXBvbGxvLmF1dG+CEioueHVlc2h1LmJhaWR1LmNvbYIRKi5iai5i
YWlkdWJjZS5jb22CESouZ3ouYmFpZHViY2UuY29tgg4qLnNtYXJ0YXBwcy5jboIN
Ki5iZHRqcmN2LmNvbYIMKi5oYW8yMjIuY29tggwqLmhhb2thbi5jb22CDyoucGFl
LmJhaWR1LmNvbYIRKi52ZC5iZHN0YXRpYy5jb22CEmNsaWNrLmhtLmJhaWR1LmNv
bYIQbG9nLmhtLmJhaWR1LmNvbYIQY20ucG9zLmJhaWR1LmNvbYIQd24ucG9zLmJh
aWR1LmNvbYIUdXBkYXRlLnBhbi5iYWlkdS5jb20wHQYDVR0lBBYwFAYIKwYBBQUH
AwEGCCsGAQUFBwMCMB8GA1UdIwQYMBaAFJbeYfG9HBYpUxzAzH07gwBA5hp8MB0G
A1UdDgQWBBSeyXnX6VurihbMMo7GmeafIEI1hzCCAX4GCisGAQQB1nkCBAIEggFu
BIIBagFoAHYAXNxDkv7mq0VEsV6a1FbmEDf71fpH3KFzlLJe5vbHDsoAAAFxObU8
ugAABAMARzBFAiBphmgxIbNZXaPWiUqXRWYLaRST38KecoekKIof5fXmsgIhAMkZ
tF8XyKCu/nZll1e9vIlKbW8RrUr/74HpmScVRRsBAHYAb1N2rDHwMRnYmQCkURX/
dxUcEdkCwQApBo2yCJo32RMAAAFxObU85AAABAMARzBFAiBURWwwTgXZ+9IV3mhm
E0EOzbg901DLRszbLIpafDY/XgIhALsvEGqbBVrpGxhKoTVlz7+GWom8SrfUeHcn
4+9Dn7xGAHYA9lyUL9F3MCIUVBgIMJRWjuNNExkzv98MLyALzE7xZOMAAAFxObU8
qwAABAMARzBFAiBFBYPxKEdhlf6bqbwxQY7tskgdoFulPxPmdrzS5tNpPwIhAKnK
qwzch98lINQYzLAV52+C8GXZPXFZNfhfpM4tQ6xbMA0GCSqGSIb3DQEBCwUAA4IB
AQC83ALQ2d6MxeLZ/k3vutEiizRCWYSSMYLVCrxANdsGshNuyM8B8V/A57c0Nzqo
CPKfMtX5IICfv9P/bUecdtHL8cfx24MzN+U/GKcA4r3a/k8pRVeHeF9ThQ2zo1xj
k/7gJl75koztdqNfOeYiBTbFMnPQzVGqyMMfqKxbJrfZlGAIgYHT9bd6T985IVgz
tRVjAoy4IurZenTsWkG7PafJ4kAh6jQaSu1zYEbHljuZ5PXlkhPO9DwW1WIPug6Z
rlylLTTYmlW3WETOATi70HYsZN6NACuZ4t1hEO3AsF7lqjdA2HwTN10FX2HuaUvf
5OzP+PKupV9VKw8x8mQKU6vr
-----END CERTIFICATE-----

以上就是QSslCertificate所提供的解析证书的接口,证书信息还有签名算法类型、签名值没有提供,颁发者和使用者提供单个信息获取,完整的字段也没有提供,当然可以全取出来自行组合

下一篇将会介绍证书链的获取及证书验签

本文标签: 证书操作信息QT