1 import { Integer as asn1jsInteger } from 'asn1js';
3 import { HOUR, SECOND, YEAR } from '@proton/shared/lib/constants';
5 import { KT_CERTIFICATE_ISSUER } from '../lib';
12 } from '../lib/verification/verifyCertificates';
13 import { letsEncryptCertificateChain, zeroSSLCertificateChain } from './verifyCertificate.data';
14 import { epoch } from './verifyKeys.data';
16 describe('certificate transparency', () => {
17 it('should fail to parse with corrupt certificate', async () => {
18 let errorThrown = true;
20 await parseCertificate('corrupt');
23 expect(err.message).toEqual("Object's schema was not verified against input data for Certificate");
25 expect(errorThrown).toEqual(true);
28 it('should fail in verifyAltName with missing extensions', async () => {
29 const { Certificate, ChainHash, EpochID, CertificateTime } = epoch;
30 const [cert] = await parseCertChain(Certificate);
31 const { extensions, ...certNoExt } = cert;
33 let errorThrown = true;
35 await verifyAltName(certNoExt, ChainHash, EpochID, CertificateTime);
38 expect(err.message).toEqual('Epoch certificate does not have extensions');
40 expect(errorThrown).toEqual(true);
43 it('should fail in verifyAltName with missing AltName extension', async () => {
44 const { Certificate, ChainHash, EpochID, CertificateTime } = epoch;
45 const [cert] = await parseCertChain(Certificate);
46 const corruptExt = cert.extensions.filter((ext) => ext.extnID !== '2.5.29.17');
48 let errorThrown = true;
50 await verifyAltName({ ...cert, extensions: corruptExt }, ChainHash, EpochID, CertificateTime);
53 expect(err.message).toEqual('Epoch certificate does not have AltName extension');
55 expect(errorThrown).toEqual(true);
58 it('should fail in verifySCT with corrupt certificate', async () => {
59 const { Certificate } = epoch;
60 const certChain = await parseCertChain(Certificate);
61 const epochCert = certChain[0];
62 const issuerCert = certChain[1];
63 epochCert.serialNumber = new asn1jsInteger();
65 let errorThrown = true;
67 await verifySCT(epochCert, issuerCert);
70 expect(err.message).toEqual('The number of verified SCTs does not reach the number of operator threshold');
72 expect(errorThrown).toEqual(true);
76 describe('certificate chain verification', () => {
77 it('Should verify 0SSL certificate', async () => {
78 const now = new Date(1709515033 * SECOND + 24 * HOUR); // 24h after epoch was published.
81 await verifyCertChain(await parseCertChain(zeroSSLCertificateChain), KT_CERTIFICATE_ISSUER.ZEROSSL, now);
85 expect(error).toBeUndefined();
87 it('Should verify LE certificate', async () => {
88 const now = new Date(1709529634 * SECOND + 24 * HOUR); // 24h after epoch was published.
91 await verifyCertChain(
92 await parseCertChain(letsEncryptCertificateChain),
93 KT_CERTIFICATE_ISSUER.LETSENCRYPT,
99 expect(error).toBeUndefined();
101 it('Should fail on expiry', async () => {
102 const now = new Date(1709529634 * SECOND + 1 * YEAR); // 1year after epoch was published.
105 await verifyCertChain(
106 await parseCertChain(letsEncryptCertificateChain),
107 KT_CERTIFICATE_ISSUER.LETSENCRYPT,
113 expect(error).toBeDefined();
114 expect(error.message).toEqual("Epoch certificate did not pass verification against issuer's certificate chain");
116 it('Should fail if the certificate is in the future', async () => {
117 const now = new Date(1709529634 * SECOND - 1 * YEAR); // 1year before epoch was published.
120 await verifyCertChain(
121 await parseCertChain(letsEncryptCertificateChain),
122 KT_CERTIFICATE_ISSUER.LETSENCRYPT,
128 expect(error).toBeDefined();
129 expect(error.message).toEqual("Epoch certificate did not pass verification against issuer's certificate chain");
131 it('Should fail if the certificate chain is broken', async () => {
132 const now = new Date(1709529634 * SECOND + 24 * HOUR); // 24h after epoch was published.
135 const zeroSSLChain = await parseCertChain(zeroSSLCertificateChain);
136 const letsEncryptChain = await parseCertChain(letsEncryptCertificateChain);
137 const chain = [letsEncryptChain[0], ...zeroSSLChain.slice(1)];
138 await verifyCertChain(chain, KT_CERTIFICATE_ISSUER.LETSENCRYPT, now);
142 expect(error).toBeDefined();
143 expect(error.message).toEqual("Epoch certificate did not pass verification against issuer's certificate chain");