如何解析 x509 证书并提取其密钥的签名算法?
How do I parse an x509 certificate and extract its key's signature algorithm?
我有一个 x509 证书作为 file/byte 数组,我想用它来验证 CertificateVerify
TLS 消息中提供的签名。我想我可以使用 SecKeyVerifySignature
once I've determined the certificate's key algorithm (SecKeyAlgorithm
parameter) and initialized the signedData
from the transcript hash(连接到上下文字符串等)。
openssl x509
报告证书的密钥,如
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:44:58:8c:d0:95:90:14:45:82:db:4f:56:41:7d:
57:0e:f5:b4:d8:65:04:6c:21:5a:cd:1e:0e:87:10:
f9:31:c6:fa:b9:ad:b3:a5:e1:df:9f:32:25:4b:a9:
40:5c:d4:56:0d:bb:55:fd:f4:68:f9:4e:89:70:56:
b9:1c:4a:ef:93
ASN1 OID: prime256v1
NIST CURVE: P-256
我相信我可以用 here 描述的机制解析证书,例如
CFDataRef certData = CFDataCreate(NULL, (const UInt8*) rawCert, len);
SecCertificateRef certificate = SecCertificateCreateWithData(NULL, certData);
而且我想我可以使用 SecCertificateCopyKey
来提取密钥,例如
SecKeyRef key = SecCertificateCopyKey(certificate);
但是,我找不到提取密钥签名算法(Public 密钥算法)的方法。我找到了 SecKeyIsAlgorithmSupported
。我是否需要遍历所有可能的 SecKeyAlgorithm
常量以找到密钥正在使用的常量(即 id-ecPublicKey
的 SecKeyAlgorithm
)?
我误解了自己的目标。
CertificateVerify
消息提供了到此为止的握手摘要。服务器使用其证书的私钥来执行该签名。如the TLS 1.3 specification所示,签名算法是CertificateVerify结构的一部分
struct {
SignatureScheme algorithm;
opaque signature<0..2^16-1>;
} CertificateVerify;
我只需要提取它并将其转换为 SecKeyAlgorithm
。例如(使用 C++)
SecKeyAlgorithm keyAlgorithm;
// algorithm extracted from CertificateVerify
switch (algorithm) {
case SignatureScheme::ecdsa_secp256r1_sha256:
keyAlgorithm = kSecKeyAlgorithmECDSASignatureDigestX962SHA256;
break;
case SignatureScheme::rsa_pss_sha256:
keyAlgorithm = kSecKeyAlgorithmRSASignatureDigestPSSSHA256;
break;
case SignatureScheme::ed25519:
case SignatureScheme::ed448:
default:
throw std::runtime_error("unsupported peer cert type");
}
然后我可以确认证书支持该算法
if (!SecKeyIsAlgorithmSupported(key, kSecKeyOperationTypeVerify, keyAlgorithm)) {
CFRelease(publicKey);
throw std::runtime_error("Unsupported signature scheme");
}
最后用CertificateVerify
中的signature
和握手编译后的签名数据进行验证
CFErrorRef error;
bool signatureVerified = SecKeyVerifySignature(key, keyAlgorithm, toBeSignedData, signature, &error);
if (!signatureVerified) {
CFRelease(error); // or use it
throw std::runtime_error("Signature verification failed");
}
我有一个 x509 证书作为 file/byte 数组,我想用它来验证 CertificateVerify
TLS 消息中提供的签名。我想我可以使用 SecKeyVerifySignature
once I've determined the certificate's key algorithm (SecKeyAlgorithm
parameter) and initialized the signedData
from the transcript hash(连接到上下文字符串等)。
openssl x509
报告证书的密钥,如
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:44:58:8c:d0:95:90:14:45:82:db:4f:56:41:7d:
57:0e:f5:b4:d8:65:04:6c:21:5a:cd:1e:0e:87:10:
f9:31:c6:fa:b9:ad:b3:a5:e1:df:9f:32:25:4b:a9:
40:5c:d4:56:0d:bb:55:fd:f4:68:f9:4e:89:70:56:
b9:1c:4a:ef:93
ASN1 OID: prime256v1
NIST CURVE: P-256
我相信我可以用 here 描述的机制解析证书,例如
CFDataRef certData = CFDataCreate(NULL, (const UInt8*) rawCert, len);
SecCertificateRef certificate = SecCertificateCreateWithData(NULL, certData);
而且我想我可以使用 SecCertificateCopyKey
来提取密钥,例如
SecKeyRef key = SecCertificateCopyKey(certificate);
但是,我找不到提取密钥签名算法(Public 密钥算法)的方法。我找到了 SecKeyIsAlgorithmSupported
。我是否需要遍历所有可能的 SecKeyAlgorithm
常量以找到密钥正在使用的常量(即 id-ecPublicKey
的 SecKeyAlgorithm
)?
我误解了自己的目标。
CertificateVerify
消息提供了到此为止的握手摘要。服务器使用其证书的私钥来执行该签名。如the TLS 1.3 specification所示,签名算法是CertificateVerify结构的一部分
struct {
SignatureScheme algorithm;
opaque signature<0..2^16-1>;
} CertificateVerify;
我只需要提取它并将其转换为 SecKeyAlgorithm
。例如(使用 C++)
SecKeyAlgorithm keyAlgorithm;
// algorithm extracted from CertificateVerify
switch (algorithm) {
case SignatureScheme::ecdsa_secp256r1_sha256:
keyAlgorithm = kSecKeyAlgorithmECDSASignatureDigestX962SHA256;
break;
case SignatureScheme::rsa_pss_sha256:
keyAlgorithm = kSecKeyAlgorithmRSASignatureDigestPSSSHA256;
break;
case SignatureScheme::ed25519:
case SignatureScheme::ed448:
default:
throw std::runtime_error("unsupported peer cert type");
}
然后我可以确认证书支持该算法
if (!SecKeyIsAlgorithmSupported(key, kSecKeyOperationTypeVerify, keyAlgorithm)) {
CFRelease(publicKey);
throw std::runtime_error("Unsupported signature scheme");
}
最后用CertificateVerify
中的signature
和握手编译后的签名数据进行验证
CFErrorRef error;
bool signatureVerified = SecKeyVerifySignature(key, keyAlgorithm, toBeSignedData, signature, &error);
if (!signatureVerified) {
CFRelease(error); // or use it
throw std::runtime_error("Signature verification failed");
}