1 import { Request } from "electron";
2 import { verifyDownloadCertificate, VerificationResult } from "./keyPinning";
4 jest.mock("electron", () => ({
5 app: { isPackaged: true },
8 const CERTIFICATE_DATA_rsa4096_badssl_com = `-----BEGIN CERTIFICATE-----
9 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
41 -----END CERTIFICATE-----`;
43 const CERTIFICATE_DATA_proton_me = `-----BEGIN CERTIFICATE-----
44 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
76 xUysZKNxowc6dl5p9hAqU/Oo9ZM=
77 -----END CERTIFICATE-----`;
79 function test_verifyDownloadCertificate(hostname: string, certificateData: string, wantResult: VerificationResult) {
80 const mockCallback = jest.fn();
83 validatedCertificate: {
84 data: certificateData,
88 verifyDownloadCertificate(r, mockCallback);
90 expect(mockCallback).toHaveBeenCalledWith(wantResult);
93 describe("key pinning", () => {
94 test("verifyDownloadCertificate is accepted from proton.me", () => {
95 test_verifyDownloadCertificate("proton.me", CERTIFICATE_DATA_proton_me, VerificationResult.Accept);
98 test("verifyDownloadCertificate is rejected with wrong certificate from proton.me", () => {
99 test_verifyDownloadCertificate("proton.me", CERTIFICATE_DATA_rsa4096_badssl_com, VerificationResult.Reject);
102 test("verifyDownloadCertificate is skipped for neverssl.com", () => {
103 test_verifyDownloadCertificate("http://neverssl.com", "", VerificationResult.UseVerificationFromChromium);
106 test("verifyDownloadCertificate is skipped for expired.badssl.com", () => {
107 test_verifyDownloadCertificate(
108 "https://expired.badssl.com",
109 CERTIFICATE_DATA_rsa4096_badssl_com,
110 VerificationResult.UseVerificationFromChromium,