Closed Bug 1415181 Opened 7 years ago Closed 7 years ago

Custom root CA + server cert trigger SEC_ERROR_BAD_DER in Firefox 56 and Nightly

Categories

(Core :: Security: PSM, defect)

defect
Not set
normal

Tracking

()

RESOLVED INVALID

People

(Reporter: pc, Unassigned)

Details

User Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36 Steps to reproduce: Visit https://gcarrier.fr/certs/ca.cert.pem and trust as root CA Add `176.58.123.25 passes` to `/etc/hosts` Visit https://passes Actual results: An error occurred during a connection to passes. security library: improperly formatted DER-encoded message. Error code: SEC_ERROR_BAD_DER Expected results: Page loads, as with Chrome and curl --cafile root.cert.pem
All certs and keys are designed to be thrown away, can be grabbed at https://gcarrier.fr/certs/ This was discovered whilst testing support for nameConstraints. The CA and cert were generated with the following code, built with Go 1.9.2 on Linux amd64, ran on Linux amd64: ``` package main import ( "time" "crypto/x509" "math/big" "crypto/x509/pkix" "net" "crypto/rsa" "log" "os" "encoding/pem" "crypto/rand" ) var notBefore = time.Date(2010, time.January, 1, 0, 0, 0, 0, time.UTC) var notAfter = time.Date(2040, time.January, 1, 0, 0, 0, 0, time.UTC) func main() { ca := x509.Certificate{ Subject: pkix.Name{Organization: []string{"localcert.org"}, CommonName: "localcert.org"}, SerialNumber: big.NewInt(1), NotBefore: notBefore, NotAfter: notAfter, IsCA: true, MaxPathLenZero: true, MaxPathLen: 0, PermittedDNSDomainsCritical: true, PermittedDNSDomains: []string{"passes"}, KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, BasicConstraintsValid: true, } passesCert := x509.Certificate{ Subject: pkix.Name{CommonName: "passes"}, SerialNumber: big.NewInt(2), NotBefore: notBefore, NotAfter: notAfter, DNSNames: []string{"passes"}, IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1), net.IPv6loopback}, KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, BasicConstraintsValid: true, } failsCert := x509.Certificate{ Subject: pkix.Name{CommonName: "fails"}, SerialNumber: big.NewInt(3), NotBefore: notBefore, NotAfter: notAfter, DNSNames: []string{"fails"}, KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, BasicConstraintsValid: true, } caPair, err := rsa.GenerateKey(rand.Reader, 4096) if err != nil { log.Fatalf("Could not generate CA keypair: %s", err) } passesPair, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { log.Fatalf("Could not generate passes keypair: %s", err) } failsPair, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { log.Fatalf("Could not generate bad keypair: %s", err) } caBytes, err := x509.CreateCertificate(rand.Reader, &ca, &ca, caPair.Public(), caPair) if err != nil { log.Fatalf("Could not create CA: %s", err) } caKeyOut, err := os.Create("ca.key.pem") if err != nil { log.Fatalf("Could no create CA key: %s", err) } err = pem.Encode(caKeyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(caPair)}) if err != nil { log.Fatalf("Could no write CA key: %s", err) } caOut, err := os.Create("ca.cert.pem") if err != nil { log.Fatalf("Could no create CA cert: %s", err) } err = pem.Encode(caOut, &pem.Block{Type: "CERTIFICATE", Bytes: caBytes}) if err != nil { log.Fatalf("Could no write CA cert: %s", err) } passesBytes, err := x509.CreateCertificate(rand.Reader, &passesCert, &ca, passesPair.Public(), caPair) if err != nil { log.Fatalf("Could not create passes cert: %s", err) } passesKeyOut, err := os.Create("passes.key.pem") if err != nil { log.Fatalf("Could no create passes key: %s", err) } err = pem.Encode(passesKeyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(passesPair)}) if err != nil { log.Fatalf("Could no write passes key: %s", err) } passesOut, err := os.Create("passes.cert.pem") if err != nil { log.Fatalf("Could no create passes cert: %s", err) } err = pem.Encode(passesOut, &pem.Block{Type: "CERTIFICATE", Bytes: passesBytes}) if err != nil { log.Fatalf("Could no write passes cert: %s", err) } failsBytes, err := x509.CreateCertificate(rand.Reader, &failsCert, &ca, failsPair.Public(), caPair) if err != nil { log.Fatalf("Could not create fails cert: %s", err) } failsKeyOut, err := os.Create("fails.key.pem") if err != nil { log.Fatalf("Could no create fails key: %s", err) } err = pem.Encode(failsKeyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(failsPair)}) if err != nil { log.Fatalf("Could no write fails key: %s", err) } failsOut, err := os.Create("fails.cert.pem") if err != nil { log.Fatalf("Could no create fails cert: %s", err) } err = pem.Encode(failsOut, &pem.Block{Type: "CERTIFICATE", Bytes: failsBytes}) if err != nil { log.Fatalf("Could no write fails cert: %s", err) } } ``` Chrome and Ubuntu 17.10 curl behave correctly (https://passes works, https://fails as the CA can't be trusted with that domain). In Firefox, https://fails fails with `SEC_ERROR_CERT_NOT_IN_NAME_SPACE` as expected; https://passes fails with `SEC_ERROR_BAD_DER`, for unknown reasons.
DER looks reasonable to me: $ sed '/^---/d' passes.cert.pem|base64 -d|under (seq/16 ; length:3 (seq/16 ; length:8 (data/0 (integer/2 2)) (integer/2 2) (seq/16 :RSA-SHA256 nil) (seq/16 (set/17 (seq/16 :O "localcert.org")) (set/17 (seq/16 :CN "localcert.org"))) (seq/16 (utctime/23 "2010-01-01T00:00:00Z") (utctime/23 "2040-01-01T00:00:00Z")) (seq/16 (set/17 (seq/16 :CN "passes"))) (seq/16 ; length:2 (seq/16 :rsaEncryption nil) (bitstring/3 ; length:270 (\str ; bytes:270 "0\x82\x01\n\x02\x82\x01\x01\x00\xA4\xA3\xC6\x81\x86&\x96\xD7" "\x87\x002r\xF4r\x1E\xC3\xE8gb\xDFf\xE7=\xED\xE7\xBA@B\x99\x1" "F\xB3mOi\xD2\xBC\xF2\xFBO\x1C\xB6\xED#\x81\xC8\"\xF3h\xC7\xB" "7\xD7\xE5\n\x83\xEC\xFEoU\x81\xB5(#|\xA7\xEEaG|\xAD\x8A\a`(b" "\xC4`\xD6\xA0\x8Ag0\x81L\xA2\e\xDC\xA0\x94\xB0\x1E\xCB\xF5\x" "B7\x0E(|\xA0\x98\x96\xDB\xCBw\xC1!\xBF\x81\x1D.\xB8)R\x9A;\x" "89\x10\xBEe\x1F\"H\x9A0O\x82z\"qN\x12\xD0\x94\x9F>\xDC\xAE\x" "F86\xBB\x94\xC8\xE1\x1D\x7F\xC5+\x18\x9E\xABF\xBDWE}\xEA\xB1" "\x91\xA8\xC5\xA8\vv\xC7\xAE85\"\xED\xB5\xE2\xD7|\x0E\xF2\x12" "\xD1\x05\x15o\xE8\xCB\f.\xFB`\x84}~r\x13\x11~\x1E\xD5d\x14|\" "xCB\x8A.\e\xCE\x8B\xD0\xCES\xCB\xEA6\nN;\x03\xDA4\x01\xF2y\x" "D5\x1A\xDE\xB3V\xEC\x9D0z\x12\x811=\xC5\xDF\e#\xE9\xFF\x92\x" "CE\xB5\x8E\xECm\x11\b\xFB\xAF\xDB\xAA{\xBB\xBD\xD8/\xAAi\xAB" "\x02\x03\x01\x00\x01"))) (data/3 ; length:1 (seq/16 ; length:4 (seq/16 :keyUsage (boolean/1 "true") (octetstring/4 "\x03\x02\x05\xA0")) (seq/16 :extendedKeyUsage (octetstring/4 "0\x14\x06\b+\x06\x01\x05\x05\a\x03\x01\x06\b+\x06\x01\x05\x05\a\x03\x02")) (seq/16 :basicConstraints (boolean/1 "true") (octetstring/4 "0\x00")) (seq/16 :subjectAltName (octetstring/4 "0 \x82\x06passes\x87\x04\x7F\x00\x00\x01\x87\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"))))) (seq/16 :RSA-SHA256 nil) (bitstring/3 ; length:512 (\str ; bytes:512 ":\x11\x9DHJ\xE8n\xE5\xA0\x16\x9F\xB0\x1D^\xFC\xC9\x15\x8FX%\" "xF7+\xD2)\xAF\xDF\xA4s\x19\xA8\xAE\x16\xEAWJ0\x94\xE4\x86\x0" "3\x1Ea\xD8VM\xAB[g\tI u\xFF3\x16\xB0\xA9\xB9\x19\xA0\xCD\xB3" "\x00>b\x83\xCE\xCB\xE1m\xE8\xB7H^:\xF32\xF2\xA1\xF0U0\x86\xF" "E\xC0c\x96l\n\x15\x12~'c\x90\x96\x88-d\x13\x89\x9DY\xA6\xC4," "\xE9\xA1|Oq\xD5\x19\xE26j@\x86\xC7\xECe\xF5\xCD\xE2rx\xB7J\x" "E7\x8C\e\xE3s`\x90'\x80\x16\x8A\x81\xC8\xFF\x16\x9E\x8B\x98\" "x95\x9F)_\xA40\x01\x18w\xE3\x99\xDB\xCC\x83\xCBj\xFA\xD3fLU\" "xD6\xF5\xA46\xBC+|\xE3\xAE,\x819\xD1|\xDD\xFC\n\x11D3^\xB1\x" "88\xC8\xB3\x04\xEA\xFB|\v\x82\x81K\x06\x96\xE2\xAB9C\"]@\xF7" "\xCA\xAAA\xD1\x90\x96\x02\x9Ds\x9A&`\xB3\xC9\xDD\xA0U\x90\x8" "Ela.\xAB\x1F\xA14X\x1F\xB2`\xFF:n}\x16\x875:J\xD9\xC8$\xEAD\" "x84\xD9\x94<\x9D\x9F\x8B!qn\xF2\x14\x8B\xEADY\e\xB9\x88\x97\" "x03\x8B0T\x9C\"\xAC|\b\xFC6,\xF7\xDE\xF6\xF310>SG\x90\xA3>zq" "v\x00\xAF(\xF1\xBF\x80\e\xB3\xD5qBsb~\x93\x88<&\xCE\b\xFDp\x" "13\xE7\x863o\f]\x1C~\xC3\xE7\x04a\xA9\x9B\x06\xBF\xC4\xB45\x" "B8j\xFA\a/\x90\xA20\xB2Wv,\xFD\xF6\xB5\x00\xD4&J11\xBC\xBB\x" "1E\xAC\xFB\xE3\x9A\xCE\xC8\xF0d\x11\xE7}\e\\i\xF6~\xDE\xEB\x" "CB\xC2x\xB1\x940g\e\x19kv\xA4\xED\e\nD\xD3\x16\xB4\xDD\x97bl" "\x10|\xC9;\xBA\nat\xD1G\b\x975\x97NIM/X\xF3\xE8w\xD1N\xFF\xA" "16\r\vN\xAF\xA1\x87\xC5<\x13\xB9\xDE\x18\x92\xC7V\xB6\xBC\"f" "\xF13{\xAA\xF8\x17\x02\xADI\x9A\x18P\n\xEB\xD7\xDAZ\xFEd5\x9" "Df{\x9E\x10*_\x02p0C\xA0\r\xE4)\xB5\x80\xEC\xF3\xD0\xDA\xF9\" "xFC;:\xE4\x97\x17\x12\xF8\xFB~\xB8q-i\xF1\xA6"))) $ sed '/^---/d' ca.cert.pem|base64 -d|under (seq/16 ; length:3 (seq/16 ; length:8 (data/0 (integer/2 2)) (integer/2 1) (seq/16 :RSA-SHA256 nil) (seq/16 (set/17 (seq/16 :O "localcert.org")) (set/17 (seq/16 :CN "localcert.org"))) (seq/16 (utctime/23 "2010-01-01T00:00:00Z") (utctime/23 "2040-01-01T00:00:00Z")) (seq/16 (set/17 (seq/16 :O "localcert.org")) (set/17 (seq/16 :CN "localcert.org"))) (seq/16 ; length:2 (seq/16 :rsaEncryption nil) (bitstring/3 ; length:526 (\str ; bytes:526 "0\x82\x02\n\x02\x82\x02\x01\x00\xC0U\xF6M*\e\x7F\xFA\xD2\xD2" "M\r\xBF\x03`\x1F\xC4e\xCA@\x92\x80\xE6\x8C\x8Cm\x8C\xBC\xC6\" "xB2\xD6\xB6\\w\xB2\xA8\x8A/\a\xE8\n\x12 \xFDa\xF1\xBDp!\xFDG" "u\x9C\xFC\x04\xA1\xF0\xB0\xF11a\x1D\x03A\xB1\xBA;\x02\x02\x8" "A\xB4\xFD\xCD0\xAF!\x15%\x0Fq\xAE\x0F\xAB\x95\xEB\xF9m\e\x15" "\xFBq$\xAA\xB8\xC1v\xFC\xD0\xBC93\xC3\xDC\xE8(4(\x02\xAA\xAD" "?\x9Dz\fF\xD62t9\xCE\xD3\x8C\x9F\xECf\xB0\x01\xCFVG\xF9U\xD6" "`8y8\x05\xC9\xF0\xAD|\x06\xDDw\xD6\xAAUld\x0F\x8E\xCAf\xEB\x" "85`\xCCV\xD8=n\x94<k7~\n\xE1Ku\x91)\v34j\xFF\xFEZ\x85`\x83y\" "x9D-i\xFF\x8C&\xA6\xF1\xB1^_zWo,Kx\xA4\x88]\x11\x80\xEEjHe\"" "\xF0\x03\x972mi}\xCE\xADO\xD4\xA3z\xA49\xCA*\x8E\xF2\xD2R\xF" "2\xD6\xC8u!\xC1\xB8o\xBD\xE7x\x18\xFD\xB7S\xD3I\x98\xB6\xD7\" "xF9\xFE\xAAN\xA0\x9F\x83\fb\xD3\xA8\xDC\x84S\x9D\x977\xCE\xB" "0\xA1LE\xE0\xA6o\xD9\x1E\xE5\xD71R\x12\x82\x9D\xBE\xB4\xC8\x" "DCd\t\xFB\xE4Z\xE25\x1A\xBFg\xAE\xCA\xA4M\xF0da\x8A\x8D\x91H" "&l\x14\xC9?\fY\a\"B\x7F\xB0\xA5\x13\e[\x16\xCD\xF7\xF8\x8F\x" "94M\x0F\xB9\xD1\x02\x94\x1AA\xA3\xEBA\xDF5\aqB\xD7\x10X\x97x" "\xB8G\xABF\xC4\xD6\xCD-\x06#n[!\x8A\xCE/\xEC\xC1\xE1\x1E\xF2" "\xA7:,\x03rnu\xE8\xC2;m\xE44\xCC[C\x05\v\xB5\xD7\xA2\x01\xE2" "\xD0bj\xFB\xD7\xD3\xBFX\t\x01U\xC8\x03\x9C\xDEu'\x10n\xD2h\x" "FF\xD8\x162oa\x1A\xA3\\\x8E\xDE\x0F\x8EQm&E\xAD\xD2\xA4V<\xA" "C\x9E\xBB\xA2\xFAj\xA1tn\xA3j\xEB\x95\xE8\x88\x11\xA0\xD1\xF" "C8\xAC\xFD\e*\xA3\xBC\xD0\x00\r\xE0\xBE\xE2\x06\xDE\xA8Co\x9" "7\xCAN\x99NK\x9E\x98![\x99\xD1v\x9B\xF9n|\xEF\x02\xA6\x8F\xB" "1\xD1\x9D\n\xAA\xC51-69\x15\x8B\x95\x02\x03\x01\x00\x01"))) (data/3 ; length:1 (seq/16 ; length:3 (seq/16 :keyUsage (boolean/1 "true") (octetstring/4 "\x03\x02\x02\x84")) (seq/16 :basicConstraints (boolean/1 "true") (octetstring/4 "0\x06\x01\x01\xFF\x02\x01\x00")) (seq/16 :nameConstraints (boolean/1 "true") (octetstring/4 "0\x0E\xA0\n0\b\x82\x06passes\xA1\x00"))))) (seq/16 :RSA-SHA256 nil) (bitstring/3 ; length:512 (\str ; bytes:512 "3\xBC\xA7\xADm\xFDXh9X\xCE\x9E\b\xDC\xE2@\x82{\x12\xD7\x9A\x" "C1y\x80\xBCHAG @\x801\xAA\xDF\xE5\xFA\x93\xA8\xD5F\xCB\xB6\x" "F6\x83w|=\x96\xA8GC\xD1\xA2V\xCC\bq\xEB\xF2I\x96n-:! \xE9\x7" "F,\xC1T\x89G\xCE3 U\x9D\xFE\xC6\xA2$Y\xB5v\x17\x1A\xB4D\xBC=" "\xFA\x9B\xAF\xA4J\x91\xA0\xB3.h\xA5\x97\xF3\r\xF9\x94\x97(E\" "xE5\xC63\xB6\x9A?V\xA6!\xEF\x7F\x91\x15G\xDE^$H\xE7)\x96\xD6" "\x8A|\x19\x1C\x14=sI\x13\xADwc\x00z\xA39aq>CZ\x06\xE8\xE5[\x" "A1\x80\xC7\x81\xD1\xD9\xD1\xD3\xB9\xA8\x0E\xC8d\xA9<s5s\xE8\" "xA2\xDEV)e3\xB2}\x9BE\x8D\xF2\x92c\x89\xEE\x9AB*\x8D-8\xC4\x" "0F\x84\xFC\xAB\x7FX\x01\x8Do\xF6\x9AWu\xB8}\xC3\xF7\x9C\xC1i" "\xF1\x03\xC0^EI\xBEg\x1A\xD0\x1A\xE9\xDCG\x15!\xFES\xAE\xD6?" "\xBB\xD1V\x1F\xD7:\xA1\xEC\xC5\x14Ca\x95?\x91?\x85\x8C\xAE\x" "F7\xDD0Rg\xB1^\n\x80\x9CWSqVAPM\xBA\x9D)\xF5t\xFB\xF0\xD7\x1" "2qA?\x86Y\x8B\x1C49\xEB\xFF!\x00z\vS\x12\x96V\xA4|\x8D\xE4\x" "C5\xE4\xAB\x8A\xF7\x17Qf\xE7\x0E\x9CtZ_$\xB2\xD8\a\\\xAF\v\x" "16\xE6\xA6\xA0\xC4t\x101\xCD\\6f!;=\xE6R\x82j\x9CsJ}\xED\xF2" ";\x8D\xA2\xEE\x98Rj\xE7\xFA\x9C\xF0\x90\xA8\xF2\xE6\x13\x12p" "\xE6&jh\xBC\x06\x02'\xF4\x8D\xEF\xAD\x06\xF4\x13\x18o\xA5\xE" "A.f\xAER!:J\xCA\x9F\xD325Fh\x86Sy\xEB\xC8\x91\xA9\xFDjY\x8A\" "x99>%\xFE\xF8\x01\x16\xC5\xAEt\xFF\x9A]\xD9|N\x8B+\xCF\xFA\x" "A7\xC60Z\x83\xDAK\xC5\xE0\xBC9\xF4\xCFw\xAFP\xFB\xFA\xEC0\xC" "6\x8DOW\xFF\x19q\vKRm\x99\xB6\xE2\"r\xC7\x93\xD3\xBEG\xD5\xB" "5\xD4\x18\x9D\xF7\x17i\xC0\xF0_\xF6\xF4ou\x9D\xDF I\xB6ET7%\" "x15y00\xFAl\x9EQ\xCD\xD8H")))
Here's what https://lapo.it/asn1js/ says about the nameConstraints extension in https://gcarrier.fr/certs/ca.cert.pem : SEQUENCE (3 elem) OBJECT IDENTIFIER 2.5.29.30 nameConstraints (X.509 extension) BOOLEAN true OCTET STRING (1 elem) SEQUENCE (2 elem) [0] (1 elem) SEQUENCE (1 elem) [2] passes [1] (0 elem) Note the empty [1]. This is the excludedSubtrees branch. I believe this is invalid because since it's present, it must have at least a GeneralName. The correct way to represent a non-present excludedSubtrees is to not include the [1] tag at all. Looking at your go code, since you're not specifying excludedSubtrees, it seems this is a bug in the implementation/API.
Fix confirmed, https://gcarrier.fr/certs updated with working certs. Demo Go code for the fix: ``` package main import ( "time" "crypto/x509" "math/big" "crypto/x509/pkix" "log" "encoding/asn1" "net" "crypto/rsa" "os" "encoding/pem" "crypto/rand" ) var notBefore = time.Date(2010, time.January, 1, 0, 0, 0, 0, time.UTC) var notAfter = time.Date(2040, time.January, 1, 0, 0, 0, 0, time.UTC) type generalSubtree struct { Name string `asn1:"tag:2,optional,ia5"` } type nameConstraints struct { Permitted []generalSubtree `asn1:"optional,tag:0"` Excluded []generalSubtree `asn1:"optional,tag:1"` } func main() { caNameConstraints, err := asn1.Marshal(nameConstraints{ Permitted: []generalSubtree{{Name: "passes"},}, }) if err != nil { log.Fatalf("Could not serialize name constraints: %s", err) } ca := x509.Certificate{ Subject: pkix.Name{Organization: []string{"localcert.org"}, CommonName: "localcert.org"}, SerialNumber: big.NewInt(1), NotBefore: notBefore, NotAfter: notAfter, IsCA: true, MaxPathLenZero: true, MaxPathLen: 0, KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, BasicConstraintsValid: true, ExtraExtensions: []pkix.Extension{{ Id: []int{2, 5, 29, 30}, Critical: true, Value: caNameConstraints, }}, } passesCert := x509.Certificate{ Subject: pkix.Name{CommonName: "passes"}, SerialNumber: big.NewInt(2), NotBefore: notBefore, NotAfter: notAfter, DNSNames: []string{"passes"}, IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1), net.IPv6loopback}, KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, BasicConstraintsValid: true, } failsCert := x509.Certificate{ Subject: pkix.Name{CommonName: "fails"}, SerialNumber: big.NewInt(3), NotBefore: notBefore, NotAfter: notAfter, DNSNames: []string{"fails"}, KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, BasicConstraintsValid: true, } caPair, err := rsa.GenerateKey(rand.Reader, 4096) if err != nil { log.Fatalf("Could not generate CA keypair: %s", err) } passesPair, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { log.Fatalf("Could not generate passes keypair: %s", err) } failsPair, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { log.Fatalf("Could not generate bad keypair: %s", err) } caBytes, err := x509.CreateCertificate(rand.Reader, &ca, &ca, caPair.Public(), caPair) if err != nil { log.Fatalf("Could not create CA: %s", err) } caKeyOut, err := os.Create("ca.key.pem") if err != nil { log.Fatalf("Could no create CA key: %s", err) } err = pem.Encode(caKeyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(caPair)}) if err != nil { log.Fatalf("Could no write CA key: %s", err) } caOut, err := os.Create("ca.cert.pem") if err != nil { log.Fatalf("Could no create CA cert: %s", err) } err = pem.Encode(caOut, &pem.Block{Type: "CERTIFICATE", Bytes: caBytes}) if err != nil { log.Fatalf("Could no write CA cert: %s", err) } passesBytes, err := x509.CreateCertificate(rand.Reader, &passesCert, &ca, passesPair.Public(), caPair) if err != nil { log.Fatalf("Could not create passes cert: %s", err) } passesKeyOut, err := os.Create("passes.key.pem") if err != nil { log.Fatalf("Could no create passes key: %s", err) } err = pem.Encode(passesKeyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(passesPair)}) if err != nil { log.Fatalf("Could no write passes key: %s", err) } passesOut, err := os.Create("passes.cert.pem") if err != nil { log.Fatalf("Could no create passes cert: %s", err) } err = pem.Encode(passesOut, &pem.Block{Type: "CERTIFICATE", Bytes: passesBytes}) if err != nil { log.Fatalf("Could no write passes cert: %s", err) } failsBytes, err := x509.CreateCertificate(rand.Reader, &failsCert, &ca, failsPair.Public(), caPair) if err != nil { log.Fatalf("Could not create fails cert: %s", err) } failsKeyOut, err := os.Create("fails.key.pem") if err != nil { log.Fatalf("Could no create fails key: %s", err) } err = pem.Encode(failsKeyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(failsPair)}) if err != nil { log.Fatalf("Could no write fails key: %s", err) } failsOut, err := os.Create("fails.cert.pem") if err != nil { log.Fatalf("Could no create fails cert: %s", err) } err = pem.Encode(failsOut, &pem.Block{Type: "CERTIFICATE", Bytes: failsBytes}) if err != nil { log.Fatalf("Could no write fails cert: %s", err) } } ```
Thanks! Closing this as "invalid", which is just bugzilla's unfortunate way of saying "not a bug in Firefox".
Status: UNCONFIRMED → RESOLVED
Closed: 7 years ago
Resolution: --- → INVALID
Many thanks for your help!
You need to log in before you can comment on or make changes to this bug.