我有一个 base 64 二进制格式的证书 x509。如何使用 Oracle 检索有关证书的信息?我必须得到这个证书的序列号。有任何想法吗?
2 回答
Oracle 论坛上有一个解决方案:SQL to extract specific attributes from an x509 digital certificate
代码(原件用于存储为 CLOB 的证书,我将其修改为 BLOB 并返回序列号):
create or replace and compile java source named testx509src
as
import java.security.cert.*;
import java.io.*;
import java.sql.*;
import oracle.sql.BLOB;
import oracle.sql.NUMBER;
public class TestX509 {
public static NUMBER getSerialNumber(BLOB cert)
throws SQLException, IOException, CertificateException {
Connection conn = (Connection) DriverManager.getConnection("jdbc:default:connection:");
BufferedInputStream is = new BufferedInputStream(cert.getBinaryStream());
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate c = (X509Certificate) cf.generateCertificate(is);
is.close();
return new oracle.sql.NUMBER(c.getSerialNumber());
}
}
/
CREATE OR REPLACE FUNCTION CERT_getSerialNumber(cert in blob)
RETURN NUMBER
AS LANGUAGE JAVA
NAME 'TestX509.getSerialNumber(oracle.sql.BLOB) return oracle.sql.NUMBER';
/
SQL> select CERT_GetSerialNumber(cert) serial from cert_storage where id = 1;
serial
-----------------------
243435653237
在对证书进行 base64 解码后,您很可能会获得 X.509 v3 证书的 DER 编码 ASN.1 结构(足够的关键字可以继续搜索答案)。
我不知道 ASN.1 解析器的任何 PL/SQL 实现,解析 DER 编码的内容,但是可以学习 ASN.1 结构(序列、整数等)及其 DER 格式的二进制表示,然后在 PL/SQL 中逐字节进行解析。=> 序列号接近 DER-content 的开头,所以不需要支持解析每个 ASN.1 元素来提取序列号。
您可能必须查看 X.509证书结构/模板,解释如何从基本 ASN.1 元素构造证书,然后解析/提取元素并获取您感兴趣的信息。
更详细的证书内容描述:X.509 证书包含一些数据字段,如版本、序列号、有效起始/截止日期、颁发者 DN(可分辨名称)、主题 DN、主题公钥、签名哈希算法等。然后,该信息由证书颁发者“签名”:颁发者根据上述信息创建一个哈希码(例如使用 SHA-1 算法),然后使用颁发者的私钥对其进行加密(RSA 加密)。拥有颁发者的公钥并信任颁发者,可以使用颁发者的公钥解密颁发者加密的哈希码,然后使用相同的算法从证书详细信息创建哈希码,最后将计算的哈希与颁发者的哈希码进行比较创建的。如果这些匹配,则意味着没有人修改细节,所以如果发行者是可信的,
X.509 证书以(右侧显示的数据类型)开头:
Certificate SEQUENCE
Data SEQUENCE
Version [0] { INTEGER }
Serial Number INTEGER
每个元素都以一个指示元素类型的标记字节开始,然后是元素长度,然后是元素内容。如果元素包含少于 128 个字节,则长度字段只需要一个字节来指定内容长度。如果超过 127 个字节,长度字段的第 7 位设置为 1,第 6 到 0 位指定用于标识内容长度的附加字节数。对于 X.509 证书,版本被包装在特定于上下文的标签 [0] 中。
可以从网上免费下载解释 ASN.1 的书籍。
Here's an example for analysing the beginning of a certificate:
30 82 02 D7 30 82 02 40 A0 03 02 01 02 02 01 01 ...
Interpretation:
30 = Start of Certificate SEQUENCE
82 = sequence length are the following two bytes
02 D7 = sequence length 0x02D7 (Big Endian order of bytes)
30 = Start of Data SEQUENCE
82 = sequence length are the following two bytes
02 40 = sequence length 0x0240 (Big Endian order of bytes)
A0 = start of context-specific element [0]
03 = length of context-specific element [0]
02 01 02 = content of context-specific element [0] (Version INTEGER)
(02=start of Version INTEGER,
01=length of the integer,
02=Version value (zero-based, so value 02 actually means v3))
02 = Start of Serial Number INTEGER
01 = Length of Serial Number INTEGER
01 = The serial number itself
...
当然,在您的情况下,序列号的长度可能大于此处显示的一个字节。