• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.SignedCertificateTimestamp = void 0;
4const util_1 = require("../util");
5const stream_1 = require("../util/stream");
6class SignedCertificateTimestamp {
7    constructor(options) {
8        this.version = options.version;
9        this.logID = options.logID;
10        this.timestamp = options.timestamp;
11        this.extensions = options.extensions;
12        this.hashAlgorithm = options.hashAlgorithm;
13        this.signatureAlgorithm = options.signatureAlgorithm;
14        this.signature = options.signature;
15    }
16    get datetime() {
17        return new Date(Number(this.timestamp.readBigInt64BE()));
18    }
19    // Returns the hash algorithm used to generate the SCT's signature.
20    // https://www.rfc-editor.org/rfc/rfc5246#section-7.4.1.4.1
21    get algorithm() {
22        switch (this.hashAlgorithm) {
23            case 0:
24                return 'none';
25            case 1:
26                return 'md5';
27            case 2:
28                return 'sha1';
29            case 3:
30                return 'sha224';
31            case 4:
32                return 'sha256';
33            case 5:
34                return 'sha384';
35            case 6:
36                return 'sha512';
37            default:
38                return 'unknown';
39        }
40    }
41    verify(preCert, logs) {
42        // Find key for the log reponsible for this signature
43        const log = logs.find((log) => log.logId?.keyId.equals(this.logID));
44        if (!log?.publicKey?.rawBytes) {
45            throw new Error(`No key found for log: ${this.logID.toString('base64')}`);
46        }
47        const publicKey = util_1.crypto.createPublicKey(log.publicKey.rawBytes);
48        // Assemble the digitally-signed struct (the data over which the signature
49        // was generated).
50        // https://www.rfc-editor.org/rfc/rfc6962#section-3.2
51        const stream = new stream_1.ByteStream();
52        stream.appendChar(this.version);
53        stream.appendChar(0x00); // SignatureType = certificate_timestamp(0)
54        stream.appendView(this.timestamp);
55        stream.appendUint16(0x01); // LogEntryType = precert_entry(1)
56        stream.appendView(preCert);
57        stream.appendUint16(this.extensions.byteLength);
58        if (this.extensions.byteLength > 0) {
59            stream.appendView(this.extensions);
60        }
61        return util_1.crypto.verifyBlob(stream.buffer, publicKey, this.signature, this.algorithm);
62    }
63    // Parses a SignedCertificateTimestamp from a buffer. SCTs are encoded using
64    // TLS encoding which means the fields and lengths of most fields are
65    // specified as part of the SCT and TLS specs.
66    // https://www.rfc-editor.org/rfc/rfc6962#section-3.2
67    // https://www.rfc-editor.org/rfc/rfc5246#section-7.4.1.4.1
68    static parse(buf) {
69        const stream = new stream_1.ByteStream(buf);
70        // Version - enum { v1(0), (255) }
71        const version = stream.getUint8();
72        // Log ID  - struct { opaque key_id[32]; }
73        const logID = stream.getBlock(32);
74        // Timestamp - uint64
75        const timestamp = stream.getBlock(8);
76        // Extensions - opaque extensions<0..2^16-1>;
77        const extenstionLength = stream.getUint16();
78        const extensions = stream.getBlock(extenstionLength);
79        // Hash algo - enum { sha256(4), . . . (255) }
80        const hashAlgorithm = stream.getUint8();
81        // Signature algo - enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
82        const signatureAlgorithm = stream.getUint8();
83        // Signature  - opaque signature<0..2^16-1>;
84        const sigLength = stream.getUint16();
85        const signature = stream.getBlock(sigLength);
86        // Check that we read the entire buffer
87        if (stream.position !== buf.length) {
88            throw new Error('SCT buffer length mismatch');
89        }
90        return new SignedCertificateTimestamp({
91            version,
92            logID,
93            timestamp,
94            extensions,
95            hashAlgorithm,
96            signatureAlgorithm,
97            signature,
98        });
99    }
100}
101exports.SignedCertificateTimestamp = SignedCertificateTimestamp;
102