pax_global_header00006660000000000000000000000064151044732270014517gustar00rootroot0000000000000052 comment=d9af71e67ed3aa920f0669e79c3a8e818ed4b8b2 golang-sslmate-src-go-pkcs12-0.6.0/000077500000000000000000000000001510447322700167305ustar00rootroot00000000000000golang-sslmate-src-go-pkcs12-0.6.0/.gitattributes000066400000000000000000000005311510447322700216220ustar00rootroot00000000000000# Treat all files in this repo as binary, with no git magic updating # line endings. Windows users contributing to Go will need to use a # modern version of git and editors capable of LF line endings. # # We'll prevent accidental CRLF line endings from entering the repo # via the git-review gofmt checks. # # See golang.org/issue/9281 * -text golang-sslmate-src-go-pkcs12-0.6.0/.gitignore000066400000000000000000000001241510447322700207150ustar00rootroot00000000000000# Add no patterns to .hgignore except for files generated by the build. last-change golang-sslmate-src-go-pkcs12-0.6.0/LICENSE000066400000000000000000000030111510447322700177300ustar00rootroot00000000000000Copyright (c) 2015, 2018, 2019 Opsmate, Inc. All rights reserved. Copyright (c) 2009 The Go Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. golang-sslmate-src-go-pkcs12-0.6.0/README.md000066400000000000000000000023061510447322700202100ustar00rootroot00000000000000# package pkcs12 [![Documentation](https://pkg.go.dev/badge/software.sslmate.com/src/go-pkcs12)](https://pkg.go.dev/software.sslmate.com/src/go-pkcs12) import "software.sslmate.com/src/go-pkcs12" Package pkcs12 implements some of PKCS#12 (also known as P12 or PFX). It is intended for decoding DER-encoded P12/PFX files for use with the `crypto/tls` package, and for encoding P12/PFX files for use by legacy applications which do not support newer formats. Since PKCS#12 uses weak encryption primitives, it SHOULD NOT be used for new applications. Note that only DER-encoded PKCS#12 files are supported, even though PKCS#12 allows BER encoding. This is because encoding/asn1 only supports DER. This package is forked from `golang.org/x/crypto/pkcs12`, which is frozen. The implementation is distilled from https://tools.ietf.org/html/rfc7292 and referenced documents. ## Import Path Note that although the source code and issue tracker for this package are hosted on GitHub, the import path is: software.sslmate.com/src/go-pkcs12 Please be sure to use this path when you `go get` and `import` this package. ## Report Issues / Send Patches Open an issue or PR at https://github.com/SSLMate/go-pkcs12 golang-sslmate-src-go-pkcs12-0.6.0/bmp-string.go000066400000000000000000000033341510447322700213440ustar00rootroot00000000000000// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package pkcs12 import ( "errors" "unicode/utf16" ) // bmpStringZeroTerminated returns s encoded in UCS-2 with a zero terminator. func bmpStringZeroTerminated(s string) ([]byte, error) { // References: // https://tools.ietf.org/html/rfc7292#appendix-B.1 // The above RFC provides the info that BMPStrings are NULL terminated. ret, err := bmpString(s) if err != nil { return nil, err } return append(ret, 0, 0), nil } // bmpString returns s encoded in UCS-2 func bmpString(s string) ([]byte, error) { // References: // https://tools.ietf.org/html/rfc7292#appendix-B.1 // https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane // - non-BMP characters are encoded in UTF 16 by using a surrogate pair of 16-bit codes // EncodeRune returns 0xfffd if the rune does not need special encoding ret := make([]byte, 0, 2*len(s)+2) for _, r := range s { if t, _ := utf16.EncodeRune(r); t != 0xfffd { return nil, errors.New("pkcs12: string contains characters that cannot be encoded in UCS-2") } ret = append(ret, byte(r/256), byte(r%256)) } return ret, nil } func decodeBMPString(bmpString []byte) (string, error) { if len(bmpString)%2 != 0 { return "", errors.New("pkcs12: odd-length BMP string") } // strip terminator if present if l := len(bmpString); l >= 2 && bmpString[l-1] == 0 && bmpString[l-2] == 0 { bmpString = bmpString[:l-2] } s := make([]uint16, 0, len(bmpString)/2) for len(bmpString) > 0 { s = append(s, uint16(bmpString[0])<<8+uint16(bmpString[1])) bmpString = bmpString[2:] } return string(utf16.Decode(s)), nil } golang-sslmate-src-go-pkcs12-0.6.0/bmp-string_test.go000066400000000000000000000040401510447322700223760ustar00rootroot00000000000000// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package pkcs12 import ( "bytes" "encoding/hex" "testing" ) var bmpStringTests = []struct { in string expectedHex string zeroTerminated bool shouldFail bool }{ {"", "0000", true, false}, {"", "", false, false}, // Example from https://tools.ietf.org/html/rfc7292#appendix-B. {"Beavis", "0042006500610076006900730000", true, false}, {"Beavis", "004200650061007600690073", false, false}, // Some characters from the "Letterlike Symbols Unicode block". {"\u2115 - Double-struck N", "21150020002d00200044006f00750062006c0065002d00730074007200750063006b0020004e0000", true, false}, {"\u2115 - Double-struck N", "21150020002d00200044006f00750062006c0065002d00730074007200750063006b0020004e", false, false}, // any character outside the BMP should trigger an error. {"\U0001f000 East wind (Mahjong)", "", true, true}, {"\U0001f000 East wind (Mahjong)", "", false, true}, } func TestBMPString(t *testing.T) { for i, test := range bmpStringTests { expected, err := hex.DecodeString(test.expectedHex) if err != nil { t.Fatalf("#%d: failed to decode expectation", i) } var out []byte if test.zeroTerminated { out, err = bmpStringZeroTerminated(test.in) } else { out, err = bmpString(test.in) } if err == nil && test.shouldFail { t.Errorf("#%d: expected to fail, but produced %x", i, out) continue } if err != nil && !test.shouldFail { t.Errorf("#%d: failed unexpectedly: %s", i, err) continue } if !test.shouldFail { if !bytes.Equal(out, expected) { t.Errorf("#%d: expected %s, got %x", i, test.expectedHex, out) continue } roundTrip, err := decodeBMPString(out) if err != nil { t.Errorf("#%d: decoding output gave an error: %s", i, err) continue } if roundTrip != test.in { t.Errorf("#%d: decoding output resulted in %q, but it should have been %q", i, roundTrip, test.in) continue } } } } golang-sslmate-src-go-pkcs12-0.6.0/crypto.go000066400000000000000000000242021510447322700205770ustar00rootroot00000000000000// Copyright 2015, 2018, 2019 Opsmate, Inc. All rights reserved. // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package pkcs12 import ( "bytes" "crypto/aes" "crypto/cipher" "crypto/des" "crypto/sha1" "crypto/sha256" "crypto/sha512" "crypto/x509/pkix" "encoding/asn1" "errors" "hash" "io" "golang.org/x/crypto/pbkdf2" "software.sslmate.com/src/go-pkcs12/internal/rc2" ) var ( oidPBEWithSHAAnd3KeyTripleDESCBC = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3}) oidPBEWithSHAAnd128BitRC2CBC = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 5}) oidPBEWithSHAAnd40BitRC2CBC = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 6}) oidPBES2 = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 5, 13}) oidPBKDF2 = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 5, 12}) oidHmacWithSHA1 = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 2, 7}) oidHmacWithSHA256 = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 2, 9}) oidHmacWithSHA512 = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 2, 11}) oidAES128CBC = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 1, 2}) oidAES192CBC = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 1, 22}) oidAES256CBC = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 1, 42}) ) // pbeCipher is an abstraction of a PKCS#12 cipher. type pbeCipher interface { // create returns a cipher.Block given a key. create(key []byte) (cipher.Block, error) // deriveKey returns a key derived from the given password and salt. deriveKey(salt, password []byte, iterations int) []byte // deriveKey returns an IV derived from the given password and salt. deriveIV(salt, password []byte, iterations int) []byte } type shaWithTripleDESCBC struct{} func (shaWithTripleDESCBC) create(key []byte) (cipher.Block, error) { return des.NewTripleDESCipher(key) } func (shaWithTripleDESCBC) deriveKey(salt, password []byte, iterations int) []byte { return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 24) } func (shaWithTripleDESCBC) deriveIV(salt, password []byte, iterations int) []byte { return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8) } type shaWith128BitRC2CBC struct{} func (shaWith128BitRC2CBC) create(key []byte) (cipher.Block, error) { return rc2.New(key, len(key)*8) } func (shaWith128BitRC2CBC) deriveKey(salt, password []byte, iterations int) []byte { return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 16) } func (shaWith128BitRC2CBC) deriveIV(salt, password []byte, iterations int) []byte { return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8) } type shaWith40BitRC2CBC struct{} func (shaWith40BitRC2CBC) create(key []byte) (cipher.Block, error) { return rc2.New(key, len(key)*8) } func (shaWith40BitRC2CBC) deriveKey(salt, password []byte, iterations int) []byte { return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 5) } func (shaWith40BitRC2CBC) deriveIV(salt, password []byte, iterations int) []byte { return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8) } type pbeParams struct { Salt []byte Iterations int } func pbeCipherFor(algorithm pkix.AlgorithmIdentifier, password []byte) (cipher.Block, []byte, error) { var cipherType pbeCipher switch { case algorithm.Algorithm.Equal(oidPBEWithSHAAnd3KeyTripleDESCBC): cipherType = shaWithTripleDESCBC{} case algorithm.Algorithm.Equal(oidPBEWithSHAAnd128BitRC2CBC): cipherType = shaWith128BitRC2CBC{} case algorithm.Algorithm.Equal(oidPBEWithSHAAnd40BitRC2CBC): cipherType = shaWith40BitRC2CBC{} case algorithm.Algorithm.Equal(oidPBES2): // rfc7292#appendix-B.1 (the original PKCS#12 PBE) requires passwords formatted as BMPStrings. // However, rfc8018#section-3 recommends that the password for PBES2 follow ASCII or UTF-8. // This is also what Windows expects. // Therefore, we convert the password to UTF-8. originalPassword, err := decodeBMPString(password) if err != nil { return nil, nil, err } utf8Password := []byte(originalPassword) return pbes2CipherFor(algorithm, utf8Password) default: return nil, nil, NotImplementedError("pbe algorithm " + algorithm.Algorithm.String() + " is not supported") } var params pbeParams if err := unmarshal(algorithm.Parameters.FullBytes, ¶ms); err != nil { return nil, nil, err } key := cipherType.deriveKey(params.Salt, password, params.Iterations) iv := cipherType.deriveIV(params.Salt, password, params.Iterations) block, err := cipherType.create(key) if err != nil { return nil, nil, err } return block, iv, nil } func pbDecrypterFor(algorithm pkix.AlgorithmIdentifier, password []byte) (cipher.BlockMode, int, error) { block, iv, err := pbeCipherFor(algorithm, password) if err != nil { return nil, 0, err } return cipher.NewCBCDecrypter(block, iv), block.BlockSize(), nil } func pbDecrypt(info decryptable, password []byte) (decrypted []byte, err error) { cbc, blockSize, err := pbDecrypterFor(info.Algorithm(), password) if err != nil { return nil, err } encrypted := info.Data() if len(encrypted) == 0 { return nil, errors.New("pkcs12: empty encrypted data") } if len(encrypted)%blockSize != 0 { return nil, errors.New("pkcs12: input is not a multiple of the block size") } decrypted = make([]byte, len(encrypted)) cbc.CryptBlocks(decrypted, encrypted) psLen := int(decrypted[len(decrypted)-1]) if psLen == 0 || psLen > blockSize { return nil, ErrDecryption } if len(decrypted) < psLen { return nil, ErrDecryption } ps := decrypted[len(decrypted)-psLen:] decrypted = decrypted[:len(decrypted)-psLen] if bytes.Compare(ps, bytes.Repeat([]byte{byte(psLen)}, psLen)) != 0 { return nil, ErrDecryption } return } // PBES2-params ::= SEQUENCE { // keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, // encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} // } type pbes2Params struct { Kdf pkix.AlgorithmIdentifier EncryptionScheme pkix.AlgorithmIdentifier } // PBKDF2-params ::= SEQUENCE { // salt CHOICE { // specified OCTET STRING, // otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}} // }, // iterationCount INTEGER (1..MAX), // keyLength INTEGER (1..MAX) OPTIONAL, // prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT // algid-hmacWithSHA1 // } type pbkdf2Params struct { Salt asn1.RawValue Iterations int KeyLength int `asn1:"optional"` Prf pkix.AlgorithmIdentifier `asn1:"optional"` } func pbes2CipherFor(algorithm pkix.AlgorithmIdentifier, password []byte) (cipher.Block, []byte, error) { var params pbes2Params if err := unmarshal(algorithm.Parameters.FullBytes, ¶ms); err != nil { return nil, nil, err } if !params.Kdf.Algorithm.Equal(oidPBKDF2) { return nil, nil, NotImplementedError("pbes2 kdf algorithm " + params.Kdf.Algorithm.String() + " is not supported") } var kdfParams pbkdf2Params if err := unmarshal(params.Kdf.Parameters.FullBytes, &kdfParams); err != nil { return nil, nil, err } if kdfParams.Salt.Tag != asn1.TagOctetString { return nil, nil, NotImplementedError("only octet string salts are supported for pbes2/pbkdf2") } var prf func() hash.Hash switch { case kdfParams.Prf.Algorithm.Equal(oidHmacWithSHA256): prf = sha256.New case kdfParams.Prf.Algorithm.Equal(oidHmacWithSHA512): prf = sha512.New case kdfParams.Prf.Algorithm.Equal(oidHmacWithSHA1): prf = sha1.New case kdfParams.Prf.Algorithm == nil: // Algorithm not specified; defaults to SHA1 according to ASN1 definition prf = sha1.New default: return nil, nil, NotImplementedError("pbes2 prf " + kdfParams.Prf.Algorithm.String() + " is not supported") } var keyLen int switch { case params.EncryptionScheme.Algorithm.Equal(oidAES256CBC): keyLen = 32 case params.EncryptionScheme.Algorithm.Equal(oidAES192CBC): keyLen = 24 case params.EncryptionScheme.Algorithm.Equal(oidAES128CBC): keyLen = 16 default: return nil, nil, NotImplementedError("pbes2 algorithm " + params.EncryptionScheme.Algorithm.String() + " is not supported") } key := pbkdf2.Key(password, kdfParams.Salt.Bytes, kdfParams.Iterations, keyLen, prf) iv := params.EncryptionScheme.Parameters.Bytes block, err := aes.NewCipher(key) if err != nil { return nil, nil, err } return block, iv, nil } // decryptable abstracts an object that contains ciphertext. type decryptable interface { Algorithm() pkix.AlgorithmIdentifier Data() []byte } func pbEncrypterFor(algorithm pkix.AlgorithmIdentifier, password []byte) (cipher.BlockMode, int, error) { block, iv, err := pbeCipherFor(algorithm, password) if err != nil { return nil, 0, err } return cipher.NewCBCEncrypter(block, iv), block.BlockSize(), nil } func pbEncrypt(info encryptable, decrypted []byte, password []byte) error { cbc, blockSize, err := pbEncrypterFor(info.Algorithm(), password) if err != nil { return err } psLen := blockSize - len(decrypted)%blockSize encrypted := make([]byte, len(decrypted)+psLen) copy(encrypted[:len(decrypted)], decrypted) copy(encrypted[len(decrypted):], bytes.Repeat([]byte{byte(psLen)}, psLen)) cbc.CryptBlocks(encrypted, encrypted) info.SetData(encrypted) return nil } // encryptable abstracts a object that contains ciphertext. type encryptable interface { Algorithm() pkix.AlgorithmIdentifier SetData([]byte) } func makePBES2Parameters(rand io.Reader, salt []byte, iterations int) ([]byte, error) { var err error randomIV := make([]byte, 16) if _, err := rand.Read(randomIV); err != nil { return nil, err } var kdfparams pbkdf2Params if kdfparams.Salt.FullBytes, err = asn1.Marshal(salt); err != nil { return nil, err } kdfparams.Iterations = iterations kdfparams.Prf.Algorithm = oidHmacWithSHA256 var params pbes2Params params.Kdf.Algorithm = oidPBKDF2 if params.Kdf.Parameters.FullBytes, err = asn1.Marshal(kdfparams); err != nil { return nil, err } params.EncryptionScheme.Algorithm = oidAES256CBC if params.EncryptionScheme.Parameters.FullBytes, err = asn1.Marshal(randomIV); err != nil { return nil, err } return asn1.Marshal(params) } golang-sslmate-src-go-pkcs12-0.6.0/crypto_test.go000066400000000000000000000121621510447322700216400ustar00rootroot00000000000000// Copyright 2015, 2018, 2019 Opsmate, Inc. All rights reserved. // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package pkcs12 import ( "bytes" "crypto/x509/pkix" "encoding/asn1" "testing" ) var sha1WithTripleDES = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3}) func TestPbDecrypterFor(t *testing.T) { params, _ := asn1.Marshal(pbeParams{ Salt: []byte{1, 2, 3, 4, 5, 6, 7, 8}, Iterations: 2048, }) alg := pkix.AlgorithmIdentifier{ Algorithm: asn1.ObjectIdentifier([]int{1, 2, 3}), Parameters: asn1.RawValue{ FullBytes: params, }, } pass, _ := bmpStringZeroTerminated("Sesame open") _, _, err := pbDecrypterFor(alg, pass) if _, ok := err.(NotImplementedError); !ok { t.Errorf("expected not implemented error, got: %T %s", err, err) } alg.Algorithm = sha1WithTripleDES cbc, blockSize, err := pbDecrypterFor(alg, pass) if err != nil { t.Errorf("unexpected error from pbDecrypterFor %v", err) } if blockSize != 8 { t.Errorf("unexpected block size %d, wanted 8", blockSize) } plaintext := []byte{1, 2, 3, 4, 5, 6, 7, 8} expectedCiphertext := []byte{185, 73, 135, 249, 137, 1, 122, 247} ciphertext := make([]byte, len(plaintext)) cbc.CryptBlocks(ciphertext, plaintext) if bytes.Compare(ciphertext, expectedCiphertext) != 0 { t.Errorf("bad ciphertext, got %x but wanted %x", ciphertext, expectedCiphertext) } } func TestPbEncrypterFor(t *testing.T) { params, _ := asn1.Marshal(pbeParams{ Salt: []byte{1, 2, 3, 4, 5, 6, 7, 8}, Iterations: 2048, }) alg := pkix.AlgorithmIdentifier{ Algorithm: asn1.ObjectIdentifier([]int{1, 2, 3}), Parameters: asn1.RawValue{ FullBytes: params, }, } pass, _ := bmpStringZeroTerminated("Sesame open") _, _, err := pbEncrypterFor(alg, pass) if _, ok := err.(NotImplementedError); !ok { t.Errorf("expected not implemented error, got: %T %s", err, err) } alg.Algorithm = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3}) cbc, _, err := pbEncrypterFor(alg, pass) if err != nil { t.Errorf("err: %v", err) } expectedM := []byte{1, 2, 3, 4, 5, 6, 7, 8} M := []byte{185, 73, 135, 249, 137, 1, 122, 247} cbc.CryptBlocks(M, M) if bytes.Compare(M, expectedM) != 0 { t.Errorf("expected M to be '%d', but found '%d", expectedM, M) } } var pbDecryptTests = []struct { in []byte expected []byte expectedError error }{ { []byte("\x33\x73\xf3\x9f\xda\x49\xae\xfc\xa0\x9a\xdf\x5a\x58\xa0\xea\x46"), // 7 padding bytes []byte("A secret!"), nil, }, { []byte("\x33\x73\xf3\x9f\xda\x49\xae\xfc\x96\x24\x2f\x71\x7e\x32\x3f\xe7"), // 8 padding bytes []byte("A secret"), nil, }, { []byte("\x35\x0c\xc0\x8d\xab\xa9\x5d\x30\x7f\x9a\xec\x6a\xd8\x9b\x9c\xd9"), // 9 padding bytes, incorrect nil, ErrDecryption, }, { []byte("\xb2\xf9\x6e\x06\x60\xae\x20\xcf\x08\xa0\x7b\xd9\x6b\x20\xef\x41"), // incorrect padding bytes: [ ... 0x04 0x02 ] nil, ErrDecryption, }, } func TestPbDecrypt(t *testing.T) { for i, test := range pbDecryptTests { decryptable := testDecryptable{ data: test.in, algorithm: pkix.AlgorithmIdentifier{ Algorithm: sha1WithTripleDES, Parameters: pbeParams{ Salt: []byte("\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8"), Iterations: 4096, }.RawASN1(), }, } password, _ := bmpStringZeroTerminated("sesame") plaintext, err := pbDecrypt(decryptable, password) if err != test.expectedError { t.Errorf("#%d: got error %q, but wanted %q", i, err, test.expectedError) continue } if !bytes.Equal(plaintext, test.expected) { t.Errorf("#%d: got %x, but wanted %x", i, plaintext, test.expected) } } } func TestPbEncrypt(t *testing.T) { tests := [][]byte{ []byte("A secret!"), []byte("A secret"), } expected := [][]byte{ []byte("\x33\x73\xf3\x9f\xda\x49\xae\xfc\xa0\x9a\xdf\x5a\x58\xa0\xea\x46"), // 7 padding bytes []byte("\x33\x73\xf3\x9f\xda\x49\xae\xfc\x96\x24\x2f\x71\x7e\x32\x3f\xe7"), // 8 padding bytes } for i, c := range tests { td := testDecryptable{ algorithm: pkix.AlgorithmIdentifier{ Algorithm: asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3}), // SHA1/3TDES Parameters: pbeParams{ Salt: []byte("\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8"), Iterations: 4096, }.RawASN1(), }, } p, _ := bmpStringZeroTerminated("sesame") err := pbEncrypt(&td, c, p) if err != nil { t.Errorf("error encrypting %d: %v", c, err) } if bytes.Compare(td.data, expected[i]) != 0 { t.Errorf("expected %d to be encrypted to %d, but found %d", c, expected[i], td.data) } } } type testDecryptable struct { data []byte algorithm pkix.AlgorithmIdentifier } func (d testDecryptable) Algorithm() pkix.AlgorithmIdentifier { return d.algorithm } func (d testDecryptable) Data() []byte { return d.data } func (d *testDecryptable) SetData(data []byte) { d.data = data } func (params pbeParams) RawASN1() (raw asn1.RawValue) { asn1Bytes, err := asn1.Marshal(params) if err != nil { panic(err) } _, err = asn1.Unmarshal(asn1Bytes, &raw) if err != nil { panic(err) } return } golang-sslmate-src-go-pkcs12-0.6.0/errors.go000066400000000000000000000013571510447322700206010ustar00rootroot00000000000000// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package pkcs12 import "errors" var ( // ErrDecryption represents a failure to decrypt the input. ErrDecryption = errors.New("pkcs12: decryption error, incorrect padding") // ErrIncorrectPassword is returned when an incorrect password is detected. // Usually, P12/PFX data is signed to be able to verify the password. ErrIncorrectPassword = errors.New("pkcs12: decryption password incorrect") ) // NotImplementedError indicates that the input is not currently supported. type NotImplementedError string func (e NotImplementedError) Error() string { return "pkcs12: " + string(e) } golang-sslmate-src-go-pkcs12-0.6.0/go.mod000066400000000000000000000001441510447322700200350ustar00rootroot00000000000000module software.sslmate.com/src/go-pkcs12 go 1.19 require golang.org/x/crypto v0.11.0 // indirect golang-sslmate-src-go-pkcs12-0.6.0/go.sum000066400000000000000000000037551510447322700200750ustar00rootroot00000000000000golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 h1:tkVvjkPTB7pnW3jnid7kNyAMPVWllTNOf/qKDze4p9o= golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang-sslmate-src-go-pkcs12-0.6.0/internal/000077500000000000000000000000001510447322700205445ustar00rootroot00000000000000golang-sslmate-src-go-pkcs12-0.6.0/internal/rc2/000077500000000000000000000000001510447322700212325ustar00rootroot00000000000000golang-sslmate-src-go-pkcs12-0.6.0/internal/rc2/bench_test.go000066400000000000000000000010571510447322700237020ustar00rootroot00000000000000// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package rc2 import ( "testing" ) func BenchmarkEncrypt(b *testing.B) { r, _ := New([]byte{0, 0, 0, 0, 0, 0, 0, 0}, 64) b.ResetTimer() var src [8]byte for i := 0; i < b.N; i++ { r.Encrypt(src[:], src[:]) } } func BenchmarkDecrypt(b *testing.B) { r, _ := New([]byte{0, 0, 0, 0, 0, 0, 0, 0}, 64) b.ResetTimer() var src [8]byte for i := 0; i < b.N; i++ { r.Decrypt(src[:], src[:]) } } golang-sslmate-src-go-pkcs12-0.6.0/internal/rc2/rc2.go000066400000000000000000000142721510447322700222550ustar00rootroot00000000000000// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package rc2 implements the RC2 cipher /* https://www.ietf.org/rfc/rfc2268.txt http://people.csail.mit.edu/rivest/pubs/KRRR98.pdf This code is licensed under the MIT license. */ package rc2 import ( "crypto/cipher" "encoding/binary" ) // The rc2 block size in bytes const BlockSize = 8 type rc2Cipher struct { k [64]uint16 } // New returns a new rc2 cipher with the given key and effective key length t1 func New(key []byte, t1 int) (cipher.Block, error) { // TODO(dgryski): error checking for key length return &rc2Cipher{ k: expandKey(key, t1), }, nil } func (*rc2Cipher) BlockSize() int { return BlockSize } var piTable = [256]byte{ 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d, 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2, 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32, 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82, 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc, 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26, 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03, 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7, 0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a, 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec, 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39, 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31, 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9, 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9, 0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e, 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad, } func expandKey(key []byte, t1 int) [64]uint16 { l := make([]byte, 128) copy(l, key) var t = len(key) var t8 = (t1 + 7) / 8 var tm = byte(255 % uint(1<<(8+uint(t1)-8*uint(t8)))) for i := len(key); i < 128; i++ { l[i] = piTable[l[i-1]+l[uint8(i-t)]] } l[128-t8] = piTable[l[128-t8]&tm] for i := 127 - t8; i >= 0; i-- { l[i] = piTable[l[i+1]^l[i+t8]] } var k [64]uint16 for i := range k { k[i] = uint16(l[2*i]) + uint16(l[2*i+1])*256 } return k } func rotl16(x uint16, b uint) uint16 { return (x >> (16 - b)) | (x << b) } func (c *rc2Cipher) Encrypt(dst, src []byte) { r0 := binary.LittleEndian.Uint16(src[0:]) r1 := binary.LittleEndian.Uint16(src[2:]) r2 := binary.LittleEndian.Uint16(src[4:]) r3 := binary.LittleEndian.Uint16(src[6:]) var j int for j <= 16 { // mix r0 r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1) r0 = rotl16(r0, 1) j++ // mix r1 r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2) r1 = rotl16(r1, 2) j++ // mix r2 r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3) r2 = rotl16(r2, 3) j++ // mix r3 r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0) r3 = rotl16(r3, 5) j++ } r0 = r0 + c.k[r3&63] r1 = r1 + c.k[r0&63] r2 = r2 + c.k[r1&63] r3 = r3 + c.k[r2&63] for j <= 40 { // mix r0 r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1) r0 = rotl16(r0, 1) j++ // mix r1 r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2) r1 = rotl16(r1, 2) j++ // mix r2 r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3) r2 = rotl16(r2, 3) j++ // mix r3 r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0) r3 = rotl16(r3, 5) j++ } r0 = r0 + c.k[r3&63] r1 = r1 + c.k[r0&63] r2 = r2 + c.k[r1&63] r3 = r3 + c.k[r2&63] for j <= 60 { // mix r0 r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1) r0 = rotl16(r0, 1) j++ // mix r1 r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2) r1 = rotl16(r1, 2) j++ // mix r2 r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3) r2 = rotl16(r2, 3) j++ // mix r3 r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0) r3 = rotl16(r3, 5) j++ } binary.LittleEndian.PutUint16(dst[0:], r0) binary.LittleEndian.PutUint16(dst[2:], r1) binary.LittleEndian.PutUint16(dst[4:], r2) binary.LittleEndian.PutUint16(dst[6:], r3) } func (c *rc2Cipher) Decrypt(dst, src []byte) { r0 := binary.LittleEndian.Uint16(src[0:]) r1 := binary.LittleEndian.Uint16(src[2:]) r2 := binary.LittleEndian.Uint16(src[4:]) r3 := binary.LittleEndian.Uint16(src[6:]) j := 63 for j >= 44 { // unmix r3 r3 = rotl16(r3, 16-5) r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0) j-- // unmix r2 r2 = rotl16(r2, 16-3) r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3) j-- // unmix r1 r1 = rotl16(r1, 16-2) r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2) j-- // unmix r0 r0 = rotl16(r0, 16-1) r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1) j-- } r3 = r3 - c.k[r2&63] r2 = r2 - c.k[r1&63] r1 = r1 - c.k[r0&63] r0 = r0 - c.k[r3&63] for j >= 20 { // unmix r3 r3 = rotl16(r3, 16-5) r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0) j-- // unmix r2 r2 = rotl16(r2, 16-3) r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3) j-- // unmix r1 r1 = rotl16(r1, 16-2) r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2) j-- // unmix r0 r0 = rotl16(r0, 16-1) r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1) j-- } r3 = r3 - c.k[r2&63] r2 = r2 - c.k[r1&63] r1 = r1 - c.k[r0&63] r0 = r0 - c.k[r3&63] for j >= 0 { // unmix r3 r3 = rotl16(r3, 16-5) r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0) j-- // unmix r2 r2 = rotl16(r2, 16-3) r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3) j-- // unmix r1 r1 = rotl16(r1, 16-2) r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2) j-- // unmix r0 r0 = rotl16(r0, 16-1) r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1) j-- } binary.LittleEndian.PutUint16(dst[0:], r0) binary.LittleEndian.PutUint16(dst[2:], r1) binary.LittleEndian.PutUint16(dst[4:], r2) binary.LittleEndian.PutUint16(dst[6:], r3) } golang-sslmate-src-go-pkcs12-0.6.0/internal/rc2/rc2_test.go000066400000000000000000000030761510447322700233140ustar00rootroot00000000000000// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package rc2 import ( "bytes" "encoding/hex" "testing" ) func TestEncryptDecrypt(t *testing.T) { // TODO(dgryski): add the rest of the test vectors from the RFC var tests = []struct { key string plain string cipher string t1 int }{ { "0000000000000000", "0000000000000000", "ebb773f993278eff", 63, }, { "ffffffffffffffff", "ffffffffffffffff", "278b27e42e2f0d49", 64, }, { "3000000000000000", "1000000000000001", "30649edf9be7d2c2", 64, }, { "88", "0000000000000000", "61a8a244adacccf0", 64, }, { "88bca90e90875a", "0000000000000000", "6ccf4308974c267f", 64, }, { "88bca90e90875a7f0f79c384627bafb2", "0000000000000000", "1a807d272bbe5db1", 64, }, { "88bca90e90875a7f0f79c384627bafb2", "0000000000000000", "2269552ab0f85ca6", 128, }, { "88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e", "0000000000000000", "5b78d3a43dfff1f1", 129, }, } for _, tt := range tests { k, _ := hex.DecodeString(tt.key) p, _ := hex.DecodeString(tt.plain) c, _ := hex.DecodeString(tt.cipher) b, _ := New(k, tt.t1) var dst [8]byte b.Encrypt(dst[:], p) if !bytes.Equal(dst[:], c) { t.Errorf("encrypt failed: got % 2x wanted % 2x\n", dst, c) } b.Decrypt(dst[:], c) if !bytes.Equal(dst[:], p) { t.Errorf("decrypt failed: got % 2x wanted % 2x\n", dst, p) } } } golang-sslmate-src-go-pkcs12-0.6.0/mac.go000066400000000000000000000125131510447322700200210ustar00rootroot00000000000000// Copyright 2015, 2018, 2019 Opsmate, Inc. All rights reserved. // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package pkcs12 import ( "crypto/hmac" "crypto/sha1" "crypto/sha256" "crypto/sha512" "crypto/x509/pkix" "encoding/asn1" "errors" "hash" "golang.org/x/crypto/pbkdf2" ) type macData struct { Mac digestInfo MacSalt []byte Iterations int `asn1:"optional,default:1"` } // from PKCS#7: type digestInfo struct { Algorithm pkix.AlgorithmIdentifier Digest []byte } // PBMAC1 parameters structure from RFC 8018 // When using PBMAC1, the MAC parameters are derived from the algorithm's Parameters field // and the macData.MacSalt and macData.Iterations fields are ignored. type pbmac1Params struct { Kdf pkix.AlgorithmIdentifier MacAlg pkix.AlgorithmIdentifier } var ( oidSHA1 = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}) oidSHA256 = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1}) oidSHA512 = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3}) oidPBMAC1 = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 5, 14}) ) // doPBMAC1 handles PBMAC1 MAC computation using parameters from Algorithm.Parameters // PBMAC1 (RFC 8018) uses PBKDF2 for key derivation and supports various HMAC algorithms. // Unlike traditional PKCS#12 MAC algorithms, PBMAC1 gets all its parameters from // the Algorithm.Parameters field, ignoring macData.MacSalt and macData.Iterations. func doPBMAC1(algorithm pkix.AlgorithmIdentifier, message, password []byte) ([]byte, error) { var params pbmac1Params if err := unmarshal(algorithm.Parameters.FullBytes, ¶ms); err != nil { return nil, err } // Only PBKDF2 is supported as KDF if !params.Kdf.Algorithm.Equal(oidPBKDF2) { return nil, NotImplementedError("PBMAC1 KDF algorithm " + params.Kdf.Algorithm.String() + " is not supported") } var kdfParams pbkdf2Params if err := unmarshal(params.Kdf.Parameters.FullBytes, &kdfParams); err != nil { return nil, err } if kdfParams.Salt.Tag != asn1.TagOctetString { return nil, NotImplementedError("only octet string salts are supported for PBMAC1/PBKDF2") } // Determine PRF function for PBKDF2 var prf func() hash.Hash switch { case kdfParams.Prf.Algorithm.Equal(oidHmacWithSHA256): prf = sha256.New case kdfParams.Prf.Algorithm.Equal(oidHmacWithSHA512): prf = sha512.New case kdfParams.Prf.Algorithm.Equal(oidHmacWithSHA1): prf = sha1.New case kdfParams.Prf.Algorithm == nil: // Algorithm not specified; defaults to SHA1 according to ASN1 definition prf = sha1.New default: return nil, NotImplementedError("PBMAC1 PRF " + kdfParams.Prf.Algorithm.String() + " is not supported") } // Determine MAC algorithm var hFn func() hash.Hash switch { case params.MacAlg.Algorithm.Equal(oidHmacWithSHA1): hFn = sha1.New case params.MacAlg.Algorithm.Equal(oidHmacWithSHA256): hFn = sha256.New case params.MacAlg.Algorithm.Equal(oidHmacWithSHA512): hFn = sha512.New default: return nil, NotImplementedError("PBMAC1 MAC algorithm " + params.MacAlg.Algorithm.String() + " is not supported") } // KeyLength is mandatory in RFC 9579 if kdfParams.KeyLength <= 0 { return nil, errors.New("pkcs12: PBMAC1 requires explicit KeyLength parameter in PBKDF2 parameters") } keyLen := kdfParams.KeyLength // Derive key using PBKDF2 key := pbkdf2.Key(password, kdfParams.Salt.Bytes, kdfParams.Iterations, keyLen, prf) // Compute HMAC mac := hmac.New(hFn, key) mac.Write(message) return mac.Sum(nil), nil } func doMac(macData *macData, message, password []byte) ([]byte, error) { // Handle PBMAC1 separately - it uses its own parameters structure from Algorithm.Parameters // and ignores macData.MacSalt and macData.Iterations fields if macData.Mac.Algorithm.Algorithm.Equal(oidPBMAC1) { // PBMAC1 expects UTF-8 passwords (for compatibility; see Erratum 7974), but // PKCS#12 passwords are BMP strings, so we convert the BMP string back to UTF-8 originalPassword, err := decodeBMPString(password) if err != nil { return nil, err } utf8Password := []byte(originalPassword) return doPBMAC1(macData.Mac.Algorithm, message, utf8Password) } var hFn func() hash.Hash var key []byte switch { case macData.Mac.Algorithm.Algorithm.Equal(oidSHA1): hFn = sha1.New key = pbkdf(sha1Sum, 20, 64, macData.MacSalt, password, macData.Iterations, 3, 20) case macData.Mac.Algorithm.Algorithm.Equal(oidSHA256): hFn = sha256.New key = pbkdf(sha256Sum, 32, 64, macData.MacSalt, password, macData.Iterations, 3, 32) case macData.Mac.Algorithm.Algorithm.Equal(oidSHA512): hFn = sha512.New key = pbkdf(sha512Sum, 64, 128, macData.MacSalt, password, macData.Iterations, 3, 64) default: return nil, NotImplementedError("MAC digest algorithm not supported: " + macData.Mac.Algorithm.Algorithm.String()) } mac := hmac.New(hFn, key) mac.Write(message) return mac.Sum(nil), nil } func verifyMac(macData *macData, message, password []byte) error { expectedMAC, err := doMac(macData, message, password) if err != nil { return err } if !hmac.Equal(macData.Mac.Digest, expectedMAC) { return ErrIncorrectPassword } return nil } func computeMac(macData *macData, message, password []byte) error { digest, err := doMac(macData, message, password) if err != nil { return err } macData.Mac.Digest = digest return nil } golang-sslmate-src-go-pkcs12-0.6.0/mac_test.go000066400000000000000000000104771510447322700210670ustar00rootroot00000000000000// Copyright 2015, 2018, 2019 Opsmate, Inc. All rights reserved. // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package pkcs12 import ( "bytes" "crypto/x509/pkix" "encoding/asn1" "testing" ) func TestVerifyMac(t *testing.T) { td := macData{ Mac: digestInfo{ Digest: []byte{0x18, 0x20, 0x3d, 0xff, 0x1e, 0x16, 0xf4, 0x92, 0xf2, 0xaf, 0xc8, 0x91, 0xa9, 0xba, 0xd6, 0xca, 0x9d, 0xee, 0x51, 0x93}, }, MacSalt: []byte{1, 2, 3, 4, 5, 6, 7, 8}, Iterations: 2048, } message := []byte{11, 12, 13, 14, 15} password, _ := bmpStringZeroTerminated("") td.Mac.Algorithm.Algorithm = asn1.ObjectIdentifier([]int{1, 2, 3}) err := verifyMac(&td, message, password) if _, ok := err.(NotImplementedError); !ok { t.Errorf("err: %v", err) } td.Mac.Algorithm.Algorithm = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}) err = verifyMac(&td, message, password) if err != ErrIncorrectPassword { t.Errorf("Expected incorrect password, got err: %v", err) } password, _ = bmpStringZeroTerminated("Sesame open") err = verifyMac(&td, message, password) if err != nil { t.Errorf("err: %v", err) } } func TestComputeMac(t *testing.T) { td := macData{ MacSalt: []byte{1, 2, 3, 4, 5, 6, 7, 8}, Iterations: 2048, } message := []byte{11, 12, 13, 14, 15} password, _ := bmpStringZeroTerminated("Sesame open") td.Mac.Algorithm.Algorithm = asn1.ObjectIdentifier([]int{1, 2, 3}) err := computeMac(&td, message, password) if _, ok := err.(NotImplementedError); !ok { t.Errorf("err: %v", err) } td.Mac.Algorithm.Algorithm = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}) err = computeMac(&td, message, password) if err != nil { t.Errorf("err: %v", err) } expectedDigest := []byte{0x18, 0x20, 0x3d, 0xff, 0x1e, 0x16, 0xf4, 0x92, 0xf2, 0xaf, 0xc8, 0x91, 0xa9, 0xba, 0xd6, 0xca, 0x9d, 0xee, 0x51, 0x93} if bytes.Compare(td.Mac.Digest, expectedDigest) != 0 { t.Errorf("Computed incorrect MAC; expected MAC to be '%d' but got '%d'", expectedDigest, td.Mac.Digest) } } func TestPBMAC1(t *testing.T) { // Create PBKDF2 parameters for PBMAC1 kdfParams := pbkdf2Params{ Salt: asn1.RawValue{Tag: asn1.TagOctetString, Bytes: []byte{1, 2, 3, 4, 5, 6, 7, 8}}, Iterations: 1000, KeyLength: 32, Prf: pkix.AlgorithmIdentifier{Algorithm: oidHmacWithSHA512}, } kdfParamsBytes, err := asn1.Marshal(kdfParams) if err != nil { t.Fatalf("Failed to marshal KDF params: %v", err) } // Create PBMAC1 parameters pbmac1Params := pbmac1Params{ Kdf: pkix.AlgorithmIdentifier{Algorithm: oidPBKDF2, Parameters: asn1.RawValue{FullBytes: kdfParamsBytes}}, MacAlg: pkix.AlgorithmIdentifier{Algorithm: oidHmacWithSHA256}, } pbmac1ParamsBytes, err := asn1.Marshal(pbmac1Params) if err != nil { t.Fatalf("Failed to marshal PBMAC1 params: %v", err) } // Create macData with PBMAC1 algorithm td := macData{ Mac: digestInfo{ Algorithm: pkix.AlgorithmIdentifier{ Algorithm: oidPBMAC1, Parameters: asn1.RawValue{FullBytes: pbmac1ParamsBytes}, }, }, // MacSalt and Iterations should be ignored for PBMAC1 MacSalt: []byte{9, 10, 11, 12}, Iterations: 999, } message := []byte{11, 12, 13, 14, 15} password, err := bmpStringZeroTerminated("test-password") if err != nil { t.Fatalf("Failed to encode password to BMP string: %v", err) } // Test MAC computation err = computeMac(&td, message, password) if err != nil { t.Errorf("Failed to compute PBMAC1: %v", err) } // Verify that MAC was computed if len(td.Mac.Digest) == 0 { t.Error("No MAC digest was computed") } if !bytes.Equal(td.Mac.Digest, []byte{0xff, 0x5c, 0x9f, 0x02, 0x8c, 0xdc, 0x21, 0xa1, 0xa1, 0x17, 0x12, 0xa8, 0xa0, 0xe4, 0xd4, 0x2d, 0xf8, 0xf6, 0x8b, 0xc5, 0xbd, 0xec, 0xe7, 0xde, 0xcf, 0xd9, 0x2e, 0x0c, 0x65, 0xcd, 0x1c, 0x6f}) { t.Error("Wrong MAC digest was computed") } // Test MAC verification err = verifyMac(&td, message, password) if err != nil { t.Errorf("Failed to verify PBMAC1: %v", err) } // Test with wrong password wrongPassword, err := bmpStringZeroTerminated("wrong-password") if err != nil { t.Fatalf("Failed to encode wrong password to BMP string: %v", err) } err = verifyMac(&td, message, wrongPassword) if err != ErrIncorrectPassword { t.Errorf("Expected ErrIncorrectPassword, got: %v", err) } } golang-sslmate-src-go-pkcs12-0.6.0/pbkdf.go000066400000000000000000000134671510447322700203600ustar00rootroot00000000000000// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package pkcs12 import ( "bytes" "crypto/sha1" "crypto/sha256" "crypto/sha512" "math/big" ) var ( one = big.NewInt(1) ) // sha1Sum returns the SHA-1 hash of in. func sha1Sum(in []byte) []byte { sum := sha1.Sum(in) return sum[:] } // sha256Sum returns the SHA-256 hash of in. func sha256Sum(in []byte) []byte { sum := sha256.Sum256(in) return sum[:] } // sha512Sum returns the SHA-512 hash of in. func sha512Sum(in []byte) []byte { sum := sha512.Sum512(in) return sum[:] } // fillWithRepeats returns v*ceiling(len(pattern) / v) bytes consisting of // repeats of pattern. func fillWithRepeats(pattern []byte, v int) []byte { if len(pattern) == 0 { return nil } outputLen := v * ((len(pattern) + v - 1) / v) return bytes.Repeat(pattern, (outputLen+len(pattern)-1)/len(pattern))[:outputLen] } func pbkdf(hash func([]byte) []byte, u, v int, salt, password []byte, r int, ID byte, size int) (key []byte) { // implementation of https://tools.ietf.org/html/rfc7292#appendix-B.2 , RFC text verbatim in comments // Let H be a hash function built around a compression function f: // Z_2^u x Z_2^v -> Z_2^u // (that is, H has a chaining variable and output of length u bits, and // the message input to the compression function of H is v bits). The // values for u and v are as follows: // HASH FUNCTION VALUE u VALUE v // MD2, MD5 128 512 // SHA-1 160 512 // SHA-224 224 512 // SHA-256 256 512 // SHA-384 384 1024 // SHA-512 512 1024 // SHA-512/224 224 1024 // SHA-512/256 256 1024 // Furthermore, let r be the iteration count. // We assume here that u and v are both multiples of 8, as are the // lengths of the password and salt strings (which we denote by p and s, // respectively) and the number n of pseudorandom bits required. In // addition, u and v are of course non-zero. // For information on security considerations for MD5 [19], see [25] and // [1], and on those for MD2, see [18]. // The following procedure can be used to produce pseudorandom bits for // a particular "purpose" that is identified by a byte called "ID". // This standard specifies 3 different values for the ID byte: // 1. If ID=1, then the pseudorandom bits being produced are to be used // as key material for performing encryption or decryption. // 2. If ID=2, then the pseudorandom bits being produced are to be used // as an IV (Initial Value) for encryption or decryption. // 3. If ID=3, then the pseudorandom bits being produced are to be used // as an integrity key for MACing. // 1. Construct a string, D (the "diversifier"), by concatenating v/8 // copies of ID. var D []byte for i := 0; i < v; i++ { D = append(D, ID) } // 2. Concatenate copies of the salt together to create a string S of // length v(ceiling(s/v)) bits (the final copy of the salt may be // truncated to create S). Note that if the salt is the empty // string, then so is S. S := fillWithRepeats(salt, v) // 3. Concatenate copies of the password together to create a string P // of length v(ceiling(p/v)) bits (the final copy of the password // may be truncated to create P). Note that if the password is the // empty string, then so is P. P := fillWithRepeats(password, v) // 4. Set I=S||P to be the concatenation of S and P. I := append(S, P...) // 5. Set c=ceiling(n/u). c := (size + u - 1) / u // 6. For i=1, 2, ..., c, do the following: A := make([]byte, c*u) var IjBuf []byte for i := 0; i < c; i++ { // A. Set A2=H^r(D||I). (i.e., the r-th hash of D||1, // H(H(H(... H(D||I)))) Ai := hash(append(D, I...)) for j := 1; j < r; j++ { Ai = hash(Ai) } copy(A[i*u:], Ai[:]) if i < c-1 { // skip on last iteration // B. Concatenate copies of Ai to create a string B of length v // bits (the final copy of Ai may be truncated to create B). var B []byte for len(B) < v { B = append(B, Ai[:]...) } B = B[:v] // C. Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit // blocks, where k=ceiling(s/v)+ceiling(p/v), modify I by // setting I_j=(I_j+B+1) mod 2^v for each j. { Bbi := new(big.Int).SetBytes(B) Ij := new(big.Int) for j := 0; j < len(I)/v; j++ { Ij.SetBytes(I[j*v : (j+1)*v]) Ij.Add(Ij, Bbi) Ij.Add(Ij, one) Ijb := Ij.Bytes() // We expect Ijb to be exactly v bytes, // if it is longer or shorter we must // adjust it accordingly. if len(Ijb) > v { Ijb = Ijb[len(Ijb)-v:] } if len(Ijb) < v { if IjBuf == nil { IjBuf = make([]byte, v) } bytesShort := v - len(Ijb) for i := 0; i < bytesShort; i++ { IjBuf[i] = 0 } copy(IjBuf[bytesShort:], Ijb) Ijb = IjBuf } copy(I[j*v:(j+1)*v], Ijb) } } } } // 7. Concatenate A_1, A_2, ..., A_c together to form a pseudorandom // bit string, A. // 8. Use the first n bits of A as the output of this entire process. return A[:size] // If the above process is being used to generate a DES key, the process // should be used to create 64 random bits, and the key's parity bits // should be set after the 64 bits have been produced. Similar concerns // hold for 2-key and 3-key triple-DES keys, for CDMF keys, and for any // similar keys with parity bits "built into them". } golang-sslmate-src-go-pkcs12-0.6.0/pbkdf_test.go000066400000000000000000000025131510447322700214050ustar00rootroot00000000000000// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package pkcs12 import ( "bytes" "testing" ) func TestThatPBKDFWorksCorrectlyForLongKeys(t *testing.T) { cipherInfo := shaWithTripleDESCBC{} salt := []byte("\xff\xff\xff\xff\xff\xff\xff\xff") password, _ := bmpStringZeroTerminated("sesame") key := cipherInfo.deriveKey(salt, password, 2048) if expected := []byte("\x7c\xd9\xfd\x3e\x2b\x3b\xe7\x69\x1a\x44\xe3\xbe\xf0\xf9\xea\x0f\xb9\xb8\x97\xd4\xe3\x25\xd9\xd1"); bytes.Compare(key, expected) != 0 { t.Fatalf("expected key '%x', but found '%x'", expected, key) } } func TestThatPBKDFHandlesLeadingZeros(t *testing.T) { // This test triggers a case where I_j (in step 6C) ends up with leading zero // byte, meaning that len(Ijb) < v (leading zeros get stripped by big.Int). // This was previously causing bug whereby certain inputs would break the // derivation and produce the wrong output. key := pbkdf(sha1Sum, 20, 64, []byte("\xf3\x7e\x05\xb5\x18\x32\x4b\x4b"), []byte("\x00\x00"), 2048, 1, 24) expected := []byte("\x00\xf7\x59\xff\x47\xd1\x4d\xd0\x36\x65\xd5\x94\x3c\xb3\xc4\xa3\x9a\x25\x55\xc0\x2a\xed\x66\xe1") if bytes.Compare(key, expected) != 0 { t.Fatalf("expected key '%x', but found '%x'", expected, key) } } golang-sslmate-src-go-pkcs12-0.6.0/pkcs12.go000066400000000000000000000774171510447322700204020ustar00rootroot00000000000000// Copyright 2015, 2018, 2019 Opsmate, Inc. All rights reserved. // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package pkcs12 implements some of PKCS#12 (also known as P12 or PFX). // It is intended for decoding DER-encoded P12/PFX files for use with the crypto/tls // package, and for encoding P12/PFX files for use by legacy applications which // do not support newer formats. Since PKCS#12 uses weak encryption // primitives, it SHOULD NOT be used for new applications. // // Note that only DER-encoded PKCS#12 files are supported, even though PKCS#12 // allows BER encoding. This is because encoding/asn1 only supports DER. // // This package is forked from golang.org/x/crypto/pkcs12, which is frozen. // The implementation is distilled from https://tools.ietf.org/html/rfc7292 // and referenced documents. package pkcs12 // import "software.sslmate.com/src/go-pkcs12" import ( "crypto/ecdsa" "crypto/rand" "crypto/rsa" "crypto/sha1" "crypto/x509" "crypto/x509/pkix" "encoding/asn1" "encoding/hex" "encoding/pem" "errors" "fmt" "io" ) // DefaultPassword is the string "changeit", a commonly-used password for // PKCS#12 files. const DefaultPassword = "changeit" // An Encoder contains methods for encoding PKCS#12 files. This package // defines several different Encoders with different parameters. // An Encoder is safe for concurrent use by multiple goroutines. type Encoder struct { macAlgorithm asn1.ObjectIdentifier certAlgorithm asn1.ObjectIdentifier keyAlgorithm asn1.ObjectIdentifier macIterations int encryptionIterations int saltLen int rand io.Reader } // WithIterations creates a new Encoder identical to enc except that // it will use the given number of KDF iterations for deriving the MAC // and encryption keys. // // Note that even with a large number of iterations, a weak // password can still be brute-forced in much less time than it would // take to brute-force a high-entropy encrytion key. For the best // security, don't worry about the number of iterations and just // use a high-entropy password (e.g. one generated with `openssl rand -hex 16`). // See https://neilmadden.blog/2023/01/09/on-pbkdf2-iterations/ for more detail. // // Panics if iterations is less than 1. func (enc Encoder) WithIterations(iterations int) *Encoder { if iterations < 1 { panic("pkcs12: number of iterations is less than 1") } enc.macIterations = iterations enc.encryptionIterations = iterations return &enc } // WithRand creates a new Encoder identical to enc except that // it will use the given io.Reader for its random number generator // instead of [crypto/rand.Reader]. func (enc Encoder) WithRand(rand io.Reader) *Encoder { enc.rand = rand return &enc } // LegacyRC2 encodes PKCS#12 files using weak algorithms that were // traditionally used in PKCS#12 files, including those produced // by OpenSSL before 3.0.0, go-pkcs12 before 0.3.0, and Java when // keystore.pkcs12.legacy is defined. Specifically, certificates // are encrypted using PBE with RC2, and keys are encrypted using PBE // with 3DES, using keys derived with 2048 iterations of HMAC-SHA-1. // MACs use HMAC-SHA-1 with keys derived with 1 iteration of HMAC-SHA-1. // // Due to the weak encryption, it is STRONGLY RECOMMENDED that you use [DefaultPassword] // when encoding PKCS#12 files using this encoder, and protect the PKCS#12 files // using other means. // // By default, OpenSSL 3 can't decode PKCS#12 files created using this encoder. // For better compatibility, use [LegacyDES]. For better security, use // [Modern2023]. var LegacyRC2 = &Encoder{ macAlgorithm: oidSHA1, certAlgorithm: oidPBEWithSHAAnd40BitRC2CBC, keyAlgorithm: oidPBEWithSHAAnd3KeyTripleDESCBC, macIterations: 1, encryptionIterations: 2048, saltLen: 8, rand: rand.Reader, } // LegacyDES encodes PKCS#12 files using weak algorithms that are // supported by a wide variety of software. Certificates and keys // are encrypted using PBE with 3DES using keys derived with 2048 // iterations of HMAC-SHA-1. MACs use HMAC-SHA-1 with keys derived // with 1 iteration of HMAC-SHA-1. These are the same parameters // used by OpenSSL's -descert option. As of 2023, this encoder is // likely to produce files that can be read by the most software. // // Due to the weak encryption, it is STRONGLY RECOMMENDED that you use [DefaultPassword] // when encoding PKCS#12 files using this encoder, and protect the PKCS#12 files // using other means. To create more secure PKCS#12 files, use [Modern2023]. var LegacyDES = &Encoder{ macAlgorithm: oidSHA1, certAlgorithm: oidPBEWithSHAAnd3KeyTripleDESCBC, keyAlgorithm: oidPBEWithSHAAnd3KeyTripleDESCBC, macIterations: 1, encryptionIterations: 2048, saltLen: 8, rand: rand.Reader, } // Passwordless encodes PKCS#12 files without any encryption or MACs. // A lot of software has trouble reading such files, so it's probably only // useful for creating Java trust stores using [Encoder.EncodeTrustStore] // or [Encoder.EncodeTrustStoreEntries]. // // When using this encoder, you MUST specify an empty password. var Passwordless = &Encoder{ macAlgorithm: nil, certAlgorithm: nil, keyAlgorithm: nil, rand: rand.Reader, } // Modern2023 encodes PKCS#12 files using algorithms that are considered modern // as of 2023. Private keys and certificates are encrypted using PBES2 with // PBKDF2-HMAC-SHA-256 and AES-256-CBC. The MAC algorithm is HMAC-SHA-2. These // are the same algorithms used by OpenSSL 3 (by default), Java 20 (by default), // and Windows Server 2019 (when "stronger" is used). // // Files produced with this encoder can be read by OpenSSL 1.1.1 and higher, // Java 12 and higher, and Windows Server 2019 and higher. // // For passwords, it is RECOMMENDED that you do one of the following: // 1) Use [DefaultPassword] and protect the file using other means, or // 2) Use a high-entropy password, such as one generated with `openssl rand -hex 16`. // // You SHOULD NOT use a lower-entropy password with this encoder because the number of KDF // iterations is only 2048 and doesn't provide meaningful protection against // brute-forcing. You can increase the number of iterations using [Encoder.WithIterations], // but as https://neilmadden.blog/2023/01/09/on-pbkdf2-iterations/ explains, this doesn't // help as much as you think. var Modern2023 = &Encoder{ macAlgorithm: oidSHA256, certAlgorithm: oidPBES2, keyAlgorithm: oidPBES2, macIterations: 2048, encryptionIterations: 2048, saltLen: 16, rand: rand.Reader, } // Legacy encodes PKCS#12 files using weak, legacy parameters that work in // a wide variety of software. // // Currently, this encoder is the same as [LegacyDES], but this // may change in the future if another encoder is found to provide better // compatibility. // // Due to the weak encryption, it is STRONGLY RECOMMENDED that you use [DefaultPassword] // when encoding PKCS#12 files using this encoder, and protect the PKCS#12 files // using other means. var Legacy = LegacyDES // Modern encodes PKCS#12 files using modern, robust parameters. // // Currently, this encoder is the same as [Modern2023], but this // may change in the future to keep up with modern practices. var Modern = Modern2023 var ( oidDataContentType = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 7, 1}) oidEncryptedDataContentType = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 7, 6}) oidFriendlyName = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 20}) oidLocalKeyID = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 21}) oidMicrosoftCSPName = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 4, 1, 311, 17, 1}) oidJavaTrustStore = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 113894, 746875, 1, 1}) oidAnyExtendedKeyUsage = asn1.ObjectIdentifier([]int{2, 5, 29, 37, 0}) ) type pfxPdu struct { Version int AuthSafe contentInfo MacData macData `asn1:"optional"` } type contentInfo struct { ContentType asn1.ObjectIdentifier Content asn1.RawValue `asn1:"tag:0,explicit,optional"` } type encryptedData struct { Version int EncryptedContentInfo encryptedContentInfo } type encryptedContentInfo struct { ContentType asn1.ObjectIdentifier ContentEncryptionAlgorithm pkix.AlgorithmIdentifier EncryptedContent []byte `asn1:"tag:0,optional"` } func (i encryptedContentInfo) Algorithm() pkix.AlgorithmIdentifier { return i.ContentEncryptionAlgorithm } func (i encryptedContentInfo) Data() []byte { return i.EncryptedContent } func (i *encryptedContentInfo) SetData(data []byte) { i.EncryptedContent = data } type safeBag struct { Id asn1.ObjectIdentifier Value asn1.RawValue `asn1:"tag:0,explicit"` Attributes []pkcs12Attribute `asn1:"set,optional"` } func (bag *safeBag) hasAttribute(id asn1.ObjectIdentifier) bool { for _, attr := range bag.Attributes { if attr.Id.Equal(id) { return true } } return false } type pkcs12Attribute struct { Id asn1.ObjectIdentifier Value asn1.RawValue `asn1:"set"` } type encryptedPrivateKeyInfo struct { AlgorithmIdentifier pkix.AlgorithmIdentifier EncryptedData []byte } func (i encryptedPrivateKeyInfo) Algorithm() pkix.AlgorithmIdentifier { return i.AlgorithmIdentifier } func (i encryptedPrivateKeyInfo) Data() []byte { return i.EncryptedData } func (i *encryptedPrivateKeyInfo) SetData(data []byte) { i.EncryptedData = data } // PEM block types const ( certificateType = "CERTIFICATE" privateKeyType = "PRIVATE KEY" ) // unmarshal calls asn1.Unmarshal, but also returns an error if there is any // trailing data after unmarshaling. func unmarshal(in []byte, out interface{}) error { trailing, err := asn1.Unmarshal(in, out) if err != nil { return err } if len(trailing) != 0 { return errors.New("pkcs12: trailing data found") } return nil } // ToPEM converts all "safe bags" contained in pfxData to PEM blocks. // // Deprecated: ToPEM creates invalid PEM blocks (private keys // are encoded as raw RSA or EC private keys rather than PKCS#8 despite being // labeled "PRIVATE KEY"). To decode a PKCS#12 file, use [DecodeChain] instead, // and use the [encoding/pem] package to convert to PEM if necessary. func ToPEM(pfxData []byte, password string) ([]*pem.Block, error) { encodedPassword, err := bmpStringZeroTerminated(password) if err != nil { return nil, ErrIncorrectPassword } bags, encodedPassword, err := getSafeContents(pfxData, encodedPassword, 2, 2) if err != nil { return nil, err } blocks := make([]*pem.Block, 0, len(bags)) for _, bag := range bags { block, err := convertBag(&bag, encodedPassword) if err != nil { return nil, err } blocks = append(blocks, block) } return blocks, nil } func convertBag(bag *safeBag, password []byte) (*pem.Block, error) { block := &pem.Block{ Headers: make(map[string]string), } for _, attribute := range bag.Attributes { k, v, err := convertAttribute(&attribute) if err != nil { return nil, err } block.Headers[k] = v } switch { case bag.Id.Equal(oidCertBag): block.Type = certificateType certsData, err := decodeCertBag(bag.Value.Bytes) if err != nil { return nil, err } block.Bytes = certsData case bag.Id.Equal(oidPKCS8ShroundedKeyBag): block.Type = privateKeyType key, err := decodePkcs8ShroudedKeyBag(bag.Value.Bytes, password) if err != nil { return nil, err } switch key := key.(type) { case *rsa.PrivateKey: block.Bytes = x509.MarshalPKCS1PrivateKey(key) case *ecdsa.PrivateKey: block.Bytes, err = x509.MarshalECPrivateKey(key) if err != nil { return nil, err } default: return nil, errors.New("pkcs12: found unknown private key type in PKCS#8 wrapping") } default: return nil, errors.New("pkcs12: don't know how to convert a safe bag of type " + bag.Id.String()) } return block, nil } func convertAttribute(attribute *pkcs12Attribute) (key, value string, err error) { isString := false switch { case attribute.Id.Equal(oidFriendlyName): key = "friendlyName" isString = true case attribute.Id.Equal(oidLocalKeyID): key = "localKeyId" case attribute.Id.Equal(oidMicrosoftCSPName): // This key is chosen to match OpenSSL. key = "Microsoft CSP Name" isString = true default: return "", "", errors.New("pkcs12: unknown attribute with OID " + attribute.Id.String()) } if isString { if err := unmarshal(attribute.Value.Bytes, &attribute.Value); err != nil { return "", "", err } if value, err = decodeBMPString(attribute.Value.Bytes); err != nil { return "", "", err } } else { var id []byte if err := unmarshal(attribute.Value.Bytes, &id); err != nil { return "", "", err } value = hex.EncodeToString(id) } return key, value, nil } // Decode extracts a certificate and private key from pfxData, which must be a DER-encoded PKCS#12 file. This function // assumes that there is only one certificate and only one private key in the // pfxData. Since PKCS#12 files often contain more than one certificate, you // probably want to use [DecodeChain] instead. func Decode(pfxData []byte, password string) (privateKey interface{}, certificate *x509.Certificate, err error) { var caCerts []*x509.Certificate privateKey, certificate, caCerts, err = DecodeChain(pfxData, password) if len(caCerts) != 0 { err = errors.New("pkcs12: expected exactly two safe bags in the PFX PDU") } return } // DecodeChain extracts a certificate, a CA certificate chain, and private key // from pfxData, which must be a DER-encoded PKCS#12 file. This function assumes that there is at least one certificate // and only one private key in the pfxData. The first certificate is assumed to // be the leaf certificate, and subsequent certificates, if any, are assumed to // comprise the CA certificate chain. func DecodeChain(pfxData []byte, password string) (privateKey interface{}, certificate *x509.Certificate, caCerts []*x509.Certificate, err error) { encodedPassword, err := bmpStringZeroTerminated(password) if err != nil { return nil, nil, nil, err } bags, encodedPassword, err := getSafeContents(pfxData, encodedPassword, 1, 2) if err != nil { return nil, nil, nil, err } for _, bag := range bags { switch { case bag.Id.Equal(oidCertBag): certsData, err := decodeCertBag(bag.Value.Bytes) if err != nil { return nil, nil, nil, err } certs, err := x509.ParseCertificates(certsData) if err != nil { return nil, nil, nil, err } if len(certs) != 1 { err = errors.New("pkcs12: expected exactly one certificate in the certBag") return nil, nil, nil, err } if certificate == nil { certificate = certs[0] } else { caCerts = append(caCerts, certs[0]) } case bag.Id.Equal(oidKeyBag): if privateKey != nil { err = errors.New("pkcs12: expected exactly one key bag") return nil, nil, nil, err } if privateKey, err = x509.ParsePKCS8PrivateKey(bag.Value.Bytes); err != nil { return nil, nil, nil, err } case bag.Id.Equal(oidPKCS8ShroundedKeyBag): if privateKey != nil { err = errors.New("pkcs12: expected exactly one key bag") return nil, nil, nil, err } if privateKey, err = decodePkcs8ShroudedKeyBag(bag.Value.Bytes, encodedPassword); err != nil { return nil, nil, nil, err } } } if certificate == nil { return nil, nil, nil, errors.New("pkcs12: certificate missing") } if privateKey == nil { return nil, nil, nil, errors.New("pkcs12: private key missing") } return } // DecodeTrustStore extracts the certificates from pfxData, which must be a DER-encoded // PKCS#12 file containing exclusively certificates with attribute 2.16.840.1.113894.746875.1.1, // which is used by Java to designate a trust anchor. // // If the password argument is empty, DecodeTrustStore will decode either password-less // PKCS#12 files (i.e. those without encryption) or files with a literal empty password. func DecodeTrustStore(pfxData []byte, password string) (certs []*x509.Certificate, err error) { encodedPassword, err := bmpStringZeroTerminated(password) if err != nil { return nil, err } bags, encodedPassword, err := getSafeContents(pfxData, encodedPassword, 1, 1) if err != nil { return nil, err } for _, bag := range bags { switch { case bag.Id.Equal(oidCertBag): if !bag.hasAttribute(oidJavaTrustStore) { return nil, errors.New("pkcs12: trust store contains a certificate that is not marked as trusted") } certsData, err := decodeCertBag(bag.Value.Bytes) if err != nil { return nil, err } parsedCerts, err := x509.ParseCertificates(certsData) if err != nil { return nil, err } if len(parsedCerts) != 1 { err = errors.New("pkcs12: expected exactly one certificate in the certBag") return nil, err } certs = append(certs, parsedCerts[0]) default: return nil, errors.New("pkcs12: expected only certificate bags") } } return } func getSafeContents(p12Data, password []byte, expectedItemsMin int, expectedItemsMax int) (bags []safeBag, updatedPassword []byte, err error) { pfx := new(pfxPdu) if err := unmarshal(p12Data, pfx); err != nil { return nil, nil, errors.New("pkcs12: error reading P12 data: " + err.Error()) } if pfx.Version != 3 { return nil, nil, NotImplementedError("can only decode v3 PFX PDU's") } if !pfx.AuthSafe.ContentType.Equal(oidDataContentType) { return nil, nil, NotImplementedError("only password-protected PFX is implemented") } // unmarshal the explicit bytes in the content for type 'data' if err := unmarshal(pfx.AuthSafe.Content.Bytes, &pfx.AuthSafe.Content); err != nil { return nil, nil, err } if len(pfx.MacData.Mac.Algorithm.Algorithm) == 0 { if !(len(password) == 2 && password[0] == 0 && password[1] == 0) { return nil, nil, errors.New("pkcs12: no MAC in data") } } else if err := verifyMac(&pfx.MacData, pfx.AuthSafe.Content.Bytes, password); err != nil { if err == ErrIncorrectPassword && len(password) == 2 && password[0] == 0 && password[1] == 0 { // some implementations use an empty byte array // for the empty string password try one more // time with empty-empty password password = nil err = verifyMac(&pfx.MacData, pfx.AuthSafe.Content.Bytes, password) } if err != nil { return nil, nil, err } } var authenticatedSafe []contentInfo if err := unmarshal(pfx.AuthSafe.Content.Bytes, &authenticatedSafe); err != nil { return nil, nil, err } if len(authenticatedSafe) < expectedItemsMin || len(authenticatedSafe) > expectedItemsMax { if expectedItemsMin == expectedItemsMax { return nil, nil, NotImplementedError(fmt.Sprintf("expected exactly %d items in the authenticated safe, but this file has %d", expectedItemsMin, len(authenticatedSafe))) } return nil, nil, NotImplementedError(fmt.Sprintf("expected between %d and %d items in the authenticated safe, but this file has %d", expectedItemsMin, expectedItemsMax, len(authenticatedSafe))) } for _, ci := range authenticatedSafe { var data []byte switch { case ci.ContentType.Equal(oidDataContentType): if err := unmarshal(ci.Content.Bytes, &data); err != nil { return nil, nil, err } case ci.ContentType.Equal(oidEncryptedDataContentType): var encryptedData encryptedData if err := unmarshal(ci.Content.Bytes, &encryptedData); err != nil { return nil, nil, err } if encryptedData.Version != 0 { return nil, nil, NotImplementedError("only version 0 of EncryptedData is supported") } if data, err = pbDecrypt(encryptedData.EncryptedContentInfo, password); err != nil { return nil, nil, err } default: return nil, nil, NotImplementedError("only data and encryptedData content types are supported in authenticated safe") } var safeContents []safeBag if err := unmarshal(data, &safeContents); err != nil { return nil, nil, err } bags = append(bags, safeContents...) } return bags, password, nil } // Encode is equivalent to LegacyRC2.WithRand(rand).Encode. // See [Encoder.Encode] and [LegacyRC2] for details. // // Deprecated: for the same behavior, use LegacyRC2.Encode; for // better compatibility, use Legacy.Encode; for better // security, use Modern.Encode. func Encode(rand io.Reader, privateKey interface{}, certificate *x509.Certificate, caCerts []*x509.Certificate, password string) (pfxData []byte, err error) { return LegacyRC2.WithRand(rand).Encode(privateKey, certificate, caCerts, password) } // Encode produces pfxData containing one private key (privateKey), an // end-entity certificate (certificate), and any number of CA certificates // (caCerts). // // The pfxData is encrypted and authenticated with keys derived from // the provided password. // // Encode emulates the behavior of OpenSSL's PKCS12_create: it creates two // SafeContents: one that's encrypted with the certificate encryption algorithm // and contains the certificates, and another that is unencrypted and contains the // private key shrouded with the key encryption algorithm. The private key bag and // the end-entity certificate bag have the LocalKeyId attribute set to the SHA-1 // fingerprint of the end-entity certificate. func (enc *Encoder) Encode(privateKey interface{}, certificate *x509.Certificate, caCerts []*x509.Certificate, password string) (pfxData []byte, err error) { if enc.macAlgorithm == nil && enc.certAlgorithm == nil && enc.keyAlgorithm == nil && password != "" { return nil, errors.New("pkcs12: password must be empty") } encodedPassword, err := bmpStringZeroTerminated(password) if err != nil { return nil, err } var pfx pfxPdu pfx.Version = 3 var certFingerprint = sha1.Sum(certificate.Raw) var localKeyIdAttr pkcs12Attribute localKeyIdAttr.Id = oidLocalKeyID localKeyIdAttr.Value.Class = 0 localKeyIdAttr.Value.Tag = 17 localKeyIdAttr.Value.IsCompound = true if localKeyIdAttr.Value.Bytes, err = asn1.Marshal(certFingerprint[:]); err != nil { return nil, err } var certBags []safeBag if certBag, err := makeCertBag(certificate.Raw, []pkcs12Attribute{localKeyIdAttr}); err != nil { return nil, err } else { certBags = append(certBags, *certBag) } for _, cert := range caCerts { if certBag, err := makeCertBag(cert.Raw, []pkcs12Attribute{}); err != nil { return nil, err } else { certBags = append(certBags, *certBag) } } var keyBag safeBag if enc.keyAlgorithm == nil { keyBag.Id = oidKeyBag keyBag.Value.Class = 2 keyBag.Value.Tag = 0 keyBag.Value.IsCompound = true if keyBag.Value.Bytes, err = x509.MarshalPKCS8PrivateKey(privateKey); err != nil { return nil, err } } else { keyBag.Id = oidPKCS8ShroundedKeyBag keyBag.Value.Class = 2 keyBag.Value.Tag = 0 keyBag.Value.IsCompound = true if keyBag.Value.Bytes, err = encodePkcs8ShroudedKeyBag(enc.rand, privateKey, enc.keyAlgorithm, encodedPassword, enc.encryptionIterations, enc.saltLen); err != nil { return nil, err } } keyBag.Attributes = append(keyBag.Attributes, localKeyIdAttr) // Construct an authenticated safe with two SafeContents. // The first SafeContents is encrypted and contains the cert bags. // The second SafeContents is unencrypted and contains the shrouded key bag. var authenticatedSafe [2]contentInfo if authenticatedSafe[0], err = makeSafeContents(enc.rand, certBags, enc.certAlgorithm, encodedPassword, enc.encryptionIterations, enc.saltLen); err != nil { return nil, err } if authenticatedSafe[1], err = makeSafeContents(enc.rand, []safeBag{keyBag}, nil, nil, 0, 0); err != nil { return nil, err } var authenticatedSafeBytes []byte if authenticatedSafeBytes, err = asn1.Marshal(authenticatedSafe[:]); err != nil { return nil, err } if enc.macAlgorithm != nil { // compute the MAC pfx.MacData.Mac.Algorithm.Algorithm = enc.macAlgorithm pfx.MacData.MacSalt = make([]byte, enc.saltLen) if _, err = enc.rand.Read(pfx.MacData.MacSalt); err != nil { return nil, err } pfx.MacData.Iterations = enc.macIterations if err = computeMac(&pfx.MacData, authenticatedSafeBytes, encodedPassword); err != nil { return nil, err } } pfx.AuthSafe.ContentType = oidDataContentType pfx.AuthSafe.Content.Class = 2 pfx.AuthSafe.Content.Tag = 0 pfx.AuthSafe.Content.IsCompound = true if pfx.AuthSafe.Content.Bytes, err = asn1.Marshal(authenticatedSafeBytes); err != nil { return nil, err } if pfxData, err = asn1.Marshal(pfx); err != nil { return nil, errors.New("pkcs12: error writing P12 data: " + err.Error()) } return } // EncodeTrustStore is equivalent to LegacyRC2.WithRand(rand).EncodeTrustStore. // See [Encoder.EncodeTrustStore] and [LegacyRC2] for details. // // Deprecated: for the same behavior, use LegacyRC2.EncodeTrustStore; to generate passwordless trust stores, // use Passwordless.EncodeTrustStore. func EncodeTrustStore(rand io.Reader, certs []*x509.Certificate, password string) (pfxData []byte, err error) { return LegacyRC2.WithRand(rand).EncodeTrustStore(certs, password) } // EncodeTrustStore produces pfxData containing any number of CA certificates // (certs) to be trusted. The certificates will be marked with a special OID that // allow it to be used as a Java TrustStore in Java 1.8 and newer. // // EncodeTrustStore creates a single SafeContents that's optionally encrypted // and contains the certificates. // // The Subject of the certificates are used as the Friendly Names (Aliases) // within the resulting pfxData. If certificates share a Subject, then the // resulting Friendly Names (Aliases) will be identical, which Java may treat as // the same entry when used as a Java TrustStore, e.g. with `keytool`. To // customize the Friendly Names, use [EncodeTrustStoreEntries]. func (enc *Encoder) EncodeTrustStore(certs []*x509.Certificate, password string) (pfxData []byte, err error) { var certsWithFriendlyNames []TrustStoreEntry for _, cert := range certs { certsWithFriendlyNames = append(certsWithFriendlyNames, TrustStoreEntry{ Cert: cert, FriendlyName: cert.Subject.String(), }) } return enc.EncodeTrustStoreEntries(certsWithFriendlyNames, password) } // TrustStoreEntry represents an entry in a Java TrustStore. type TrustStoreEntry struct { Cert *x509.Certificate FriendlyName string } // EncodeTrustStoreEntries is equivalent to LegacyRC2.WithRand(rand).EncodeTrustStoreEntries. // See [Encoder.EncodeTrustStoreEntries] and [LegacyRC2] for details. // // Deprecated: for the same behavior, use LegacyRC2.EncodeTrustStoreEntries; to generate passwordless trust stores, // use Passwordless.EncodeTrustStoreEntries. func EncodeTrustStoreEntries(rand io.Reader, entries []TrustStoreEntry, password string) (pfxData []byte, err error) { return LegacyRC2.WithRand(rand).EncodeTrustStoreEntries(entries, password) } // EncodeTrustStoreEntries produces pfxData containing any number of CA // certificates (entries) to be trusted. The certificates will be marked with a // special OID that allow it to be used as a Java TrustStore in Java 1.8 and newer. // // This is identical to [Encoder.EncodeTrustStore], but also allows for setting specific // Friendly Names (Aliases) to be used per certificate, by specifying a slice // of TrustStoreEntry. // // If the same Friendly Name is used for more than one certificate, then the // resulting Friendly Names (Aliases) in the pfxData will be identical, which Java // may treat as the same entry when used as a Java TrustStore, e.g. with `keytool`. // // EncodeTrustStoreEntries creates a single SafeContents that's optionally // encrypted and contains the certificates. func (enc *Encoder) EncodeTrustStoreEntries(entries []TrustStoreEntry, password string) (pfxData []byte, err error) { if enc.macAlgorithm == nil && enc.certAlgorithm == nil && password != "" { return nil, errors.New("pkcs12: password must be empty") } encodedPassword, err := bmpStringZeroTerminated(password) if err != nil { return nil, err } var pfx pfxPdu pfx.Version = 3 var certAttributes []pkcs12Attribute extKeyUsageOidBytes, err := asn1.Marshal(oidAnyExtendedKeyUsage) if err != nil { return nil, err } // the oidJavaTrustStore attribute contains the EKUs for which // this trust anchor will be valid certAttributes = append(certAttributes, pkcs12Attribute{ Id: oidJavaTrustStore, Value: asn1.RawValue{ Class: 0, Tag: 17, IsCompound: true, Bytes: extKeyUsageOidBytes, }, }) var certBags []safeBag for _, entry := range entries { bmpFriendlyName, err := bmpString(entry.FriendlyName) if err != nil { return nil, err } encodedFriendlyName, err := asn1.Marshal(asn1.RawValue{ Class: 0, Tag: 30, IsCompound: false, Bytes: bmpFriendlyName, }) if err != nil { return nil, err } friendlyName := pkcs12Attribute{ Id: oidFriendlyName, Value: asn1.RawValue{ Class: 0, Tag: 17, IsCompound: true, Bytes: encodedFriendlyName, }, } certBag, err := makeCertBag(entry.Cert.Raw, append(certAttributes, friendlyName)) if err != nil { return nil, err } certBags = append(certBags, *certBag) } // Construct an authenticated safe with one SafeContent. // The SafeContents is contains the cert bags. var authenticatedSafe [1]contentInfo if authenticatedSafe[0], err = makeSafeContents(enc.rand, certBags, enc.certAlgorithm, encodedPassword, enc.encryptionIterations, enc.saltLen); err != nil { return nil, err } var authenticatedSafeBytes []byte if authenticatedSafeBytes, err = asn1.Marshal(authenticatedSafe[:]); err != nil { return nil, err } if enc.macAlgorithm != nil { // compute the MAC pfx.MacData.Mac.Algorithm.Algorithm = enc.macAlgorithm pfx.MacData.MacSalt = make([]byte, enc.saltLen) if _, err = enc.rand.Read(pfx.MacData.MacSalt); err != nil { return nil, err } pfx.MacData.Iterations = enc.macIterations if err = computeMac(&pfx.MacData, authenticatedSafeBytes, encodedPassword); err != nil { return nil, err } } pfx.AuthSafe.ContentType = oidDataContentType pfx.AuthSafe.Content.Class = 2 pfx.AuthSafe.Content.Tag = 0 pfx.AuthSafe.Content.IsCompound = true if pfx.AuthSafe.Content.Bytes, err = asn1.Marshal(authenticatedSafeBytes); err != nil { return nil, err } if pfxData, err = asn1.Marshal(pfx); err != nil { return nil, errors.New("pkcs12: error writing P12 data: " + err.Error()) } return } func makeCertBag(certBytes []byte, attributes []pkcs12Attribute) (certBag *safeBag, err error) { certBag = new(safeBag) certBag.Id = oidCertBag certBag.Value.Class = 2 certBag.Value.Tag = 0 certBag.Value.IsCompound = true if certBag.Value.Bytes, err = encodeCertBag(certBytes); err != nil { return nil, err } certBag.Attributes = attributes return } func makeSafeContents(rand io.Reader, bags []safeBag, algoID asn1.ObjectIdentifier, password []byte, iterations int, saltLen int) (ci contentInfo, err error) { var data []byte if data, err = asn1.Marshal(bags); err != nil { return } if algoID == nil { ci.ContentType = oidDataContentType ci.Content.Class = 2 ci.Content.Tag = 0 ci.Content.IsCompound = true if ci.Content.Bytes, err = asn1.Marshal(data); err != nil { return } } else { randomSalt := make([]byte, saltLen) if _, err = rand.Read(randomSalt); err != nil { return } var algo pkix.AlgorithmIdentifier algo.Algorithm = algoID if algoID.Equal(oidPBES2) { if algo.Parameters.FullBytes, err = makePBES2Parameters(rand, randomSalt, iterations); err != nil { return } } else { if algo.Parameters.FullBytes, err = asn1.Marshal(pbeParams{Salt: randomSalt, Iterations: iterations}); err != nil { return } } var encryptedData encryptedData encryptedData.Version = 0 encryptedData.EncryptedContentInfo.ContentType = oidDataContentType encryptedData.EncryptedContentInfo.ContentEncryptionAlgorithm = algo if err = pbEncrypt(&encryptedData.EncryptedContentInfo, data, password); err != nil { return } ci.ContentType = oidEncryptedDataContentType ci.Content.Class = 2 ci.Content.Tag = 0 ci.Content.IsCompound = true if ci.Content.Bytes, err = asn1.Marshal(encryptedData); err != nil { return } } return } golang-sslmate-src-go-pkcs12-0.6.0/pkcs12_pbmac1_test.go000066400000000000000000000114321510447322700226450ustar00rootroot00000000000000package pkcs12 import ( "encoding/base64" "os" "path/filepath" "testing" ) func loadTestData(t *testing.T, filename string) []byte { base64data, err := os.ReadFile(filepath.Join("testdata", filename)) if err != nil { t.Fatalf("failed to load test data: %v", err) } rawData, err := base64.StdEncoding.DecodeString(string(base64data)) if err != nil { t.Fatalf("failed to decode test data %q: %v", filename, err) } return rawData } // RFC 9579 Appendix A.1 func TestDecodePKCS12DataOk(t *testing.T) { pfxData := loadTestData(t, "rfc9579-a1.txt") password := "1234" encodedPassword, err := bmpStringZeroTerminated(password) if err != nil { t.Fatalf("Failed to encode password to BMP string: %v", err) } safeContents, updatedPassword, err := getSafeContents(pfxData, encodedPassword, 1, 10) if err != nil { t.Fatalf("Failed to load PKCS#12 data with getSafeContents: %v", err) } if len(safeContents) == 0 { t.Error("Expected non-empty safe contents") } t.Logf("Successfully loaded PKCS#12 data with %d safe bag(s)", len(safeContents)) t.Logf("Updated password length: %d", len(updatedPassword)) for i, bag := range safeContents { t.Logf(" Bag %d: ID=%s", i, bag.Id.String()) } } // RFC 9579 Appendix A.2 func TestDecodePKCS12DataSha256Sha512(t *testing.T) { pfxData := loadTestData(t, "rfc9579-a2.txt") password := "1234" encodedPassword, err := bmpStringZeroTerminated(password) if err != nil { t.Fatalf("Failed to encode password to BMP string: %v", err) } safeContents, updatedPassword, err := getSafeContents(pfxData, encodedPassword, 1, 10) if err != nil { t.Fatalf("Failed to load PKCS#12 data with getSafeContents: %v", err) } if len(safeContents) == 0 { t.Error("Expected non-empty safe contents") } t.Logf("Successfully loaded PKCS#12 SHA256/SHA512 data with %d safe bag(s)", len(safeContents)) t.Logf("Updated password length: %d", len(updatedPassword)) for i, bag := range safeContents { t.Logf(" Bag %d: ID=%s", i, bag.Id.String()) } } // RFC 9579 Appendix A.3 func TestDecodePKCS12DataSha512Sha512(t *testing.T) { pfxData := loadTestData(t, "rfc9579-a3.txt") password := "1234" encodedPassword, err := bmpStringZeroTerminated(password) if err != nil { t.Fatalf("Failed to encode password to BMP string: %v", err) } safeContents, updatedPassword, err := getSafeContents(pfxData, encodedPassword, 1, 10) if err != nil { t.Fatalf("Failed to load PKCS#12 data with getSafeContents: %v", err) } if len(safeContents) == 0 { t.Error("Expected non-empty safe contents") } t.Logf("Successfully loaded PKCS#12 SHA512/SHA512 data with %d safe bag(s)", len(safeContents)) t.Logf("Updated password length: %d", len(updatedPassword)) for i, bag := range safeContents { t.Logf(" Bag %d: ID=%s", i, bag.Id.String()) } } // RFC 9579 Appendix A.4 // Test with bad iteration count func TestDecodePKCS12DataBadIterationCount(t *testing.T) { pfxData := loadTestData(t, "rfc9579-a4.txt") password := "1234" encodedPassword, err := bmpStringZeroTerminated(password) if err != nil { t.Fatalf("Failed to encode password to BMP string: %v", err) } _, _, err = getSafeContents(pfxData, encodedPassword, 1, 10) if err == nil { t.Fatal("Expected getSafeContents to fail with bad iteration count, but it succeeded") } if err != ErrIncorrectPassword { t.Fatalf("Got error %v but expected %v", err, ErrIncorrectPassword) } t.Logf("Successfully detected bad iteration count: %v", err) } // RFC 9579 Appendix A.5 // Test with incorrect salt func TestDecodePKCS12DataIncorrectSalt(t *testing.T) { pfxData := loadTestData(t, "rfc9579-a5.txt") password := "1234" encodedPassword, err := bmpStringZeroTerminated(password) if err != nil { t.Fatalf("Failed to encode password to BMP string: %v", err) } _, _, err = getSafeContents(pfxData, encodedPassword, 1, 10) if err == nil { t.Fatal("Expected getSafeContents to fail with incorrect salt, but it succeeded") } if err != ErrIncorrectPassword { t.Fatalf("Got error %v but expected %v", err, ErrIncorrectPassword) } t.Logf("Successfully detected incorrect salt: %v", err) } // RFC 9579 Appendix A.6 // Test with missing key length func TestDecodePKCS12DataMissingKeyLength(t *testing.T) { pfxData := loadTestData(t, "rfc9579-a6.txt") password := "1234" encodedPassword, err := bmpStringZeroTerminated(password) if err != nil { t.Fatalf("Failed to encode password to BMP string: %v", err) } _, _, err = getSafeContents(pfxData, encodedPassword, 1, 10) if err == nil { t.Fatal("Expected getSafeContents to fail with missing key length, but it succeeded") } if expected := "pkcs12: PBMAC1 requires explicit KeyLength parameter in PBKDF2 parameters"; err.Error() != expected { t.Fatalf("Got error %v but expected %v", err.Error(), expected) } t.Logf("Successfully detected missing key length: %v", err) } golang-sslmate-src-go-pkcs12-0.6.0/pkcs12_test.go000066400000000000000000000610321510447322700214230ustar00rootroot00000000000000// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package pkcs12 import ( "crypto/rand" "crypto/rsa" "crypto/tls" "crypto/x509" "encoding/base64" "encoding/pem" "testing" ) func TestPfx(t *testing.T) { for commonName, base64P12 := range testdata { p12, _ := base64.StdEncoding.DecodeString(base64P12) priv, cert, err := Decode(p12, "") if err != nil { t.Fatal(err) } if err := priv.(*rsa.PrivateKey).Validate(); err != nil { t.Errorf("error while validating private key: %v", err) } if cert.Subject.CommonName != commonName { t.Errorf("expected common name to be %q, but found %q", commonName, cert.Subject.CommonName) } } } func TestPEM(t *testing.T) { for commonName, base64P12 := range testdata { p12, _ := base64.StdEncoding.DecodeString(base64P12) blocks, err := ToPEM(p12, "") if err != nil { t.Fatalf("error while converting to PEM: %s", err) } var pemData []byte for _, b := range blocks { pemData = append(pemData, pem.EncodeToMemory(b)...) } cert, err := tls.X509KeyPair(pemData, pemData) if err != nil { t.Errorf("err while converting to key pair: %v", err) } config := tls.Config{ Certificates: []tls.Certificate{cert}, } config.BuildNameToCertificate() if _, exists := config.NameToCertificate[commonName]; !exists { t.Errorf("did not find our cert in PEM?: %v", config.NameToCertificate) } } } func TestTrustStore(t *testing.T) { for commonName, base64P12 := range testdata { p12, _ := base64.StdEncoding.DecodeString(base64P12) _, cert, err := Decode(p12, "") if err != nil { t.Fatal(err) } pfxData, err := EncodeTrustStore(rand.Reader, []*x509.Certificate{cert}, "password") if err != nil { t.Fatal(err) } decodedCerts, err := DecodeTrustStore(pfxData, "password") if err != nil { t.Fatal(err) } if len(decodedCerts) != 1 { t.Fatal("Unexpected number of certs") } if decodedCerts[0].Subject.CommonName != commonName { t.Errorf("expected common name to be %q, but found %q", commonName, decodedCerts[0].Subject.CommonName) } } } func TestPBES2_AES256CBC(t *testing.T) { // This P12 PDU is a self-signed certificate exported via Windows certmgr. // It is encrypted with the following options (verified via openssl): PBES2, PBKDF2, AES-256-CBC, Iteration 2000, PRF hmacWithSHA256 commonName := "*.ad.standalone.com" base64P12 := `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` p12, _ := base64.StdEncoding.DecodeString(base64P12) pk, cert, caCerts, err := DecodeChain(p12, "password") if err != nil { t.Fatal(err) } rsaPk, ok := pk.(*rsa.PrivateKey) if !ok { t.Error("could not cast to rsa private key") } if !rsaPk.PublicKey.Equal(cert.PublicKey) { t.Error("public key embedded in private key not equal to public key of certificate") } if cert.Subject.CommonName != commonName { t.Errorf("unexpected leaf cert common name, got %s, want %s", cert.Subject.CommonName, commonName) } if len(caCerts) != 0 { t.Errorf("unexpected # of caCerts: got %d, want 0", len(caCerts)) } } func TestPBES2_AES128CBC(t *testing.T) { //PKCS7 Encrypted data: PBES2, PBKDF2, AES-128-CBC, Iteration 2048, PRF hmacWithSHA256 commonName := "example-com" base64P12 := `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` p12, _ := base64.StdEncoding.DecodeString(base64P12) pk, cert, caCerts, err := DecodeChain(p12, "rHyQTJsubhfxcpH5JttyilHE6BBsNoZp") if err != nil { t.Fatal(err) } rsaPk, ok := pk.(*rsa.PrivateKey) if !ok { t.Error("could not cast to rsa private key") } if !rsaPk.PublicKey.Equal(cert.PublicKey) { t.Error("public key embedded in private key not equal to public key of certificate") } if cert.Subject.CommonName != commonName { t.Errorf("unexpected leaf cert common name, got %s, want %s", cert.Subject.CommonName, commonName) } if len(caCerts) != 0 { t.Errorf("unexpected # of caCerts: got %d, want 0", len(caCerts)) } } func TestPBES2_AES192CBC(t *testing.T) { //PKCS7 Encrypted data: PBES2, PBKDF2, AES-192-CBC, Iteration 2048, PRF hmacWithSHA256 commonName := "example-com" base64P12 := `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` p12, _ := base64.StdEncoding.DecodeString(base64P12) pk, cert, caCerts, err := DecodeChain(p12, "password") if err != nil { t.Fatal(err) } rsaPk, ok := pk.(*rsa.PrivateKey) if !ok { t.Error("could not cast to rsa private key") } if !rsaPk.PublicKey.Equal(cert.PublicKey) { t.Error("public key embedded in private key not equal to public key of certificate") } if cert.Subject.CommonName != commonName { t.Errorf("unexpected leaf cert common name, got %s, want %s", cert.Subject.CommonName, commonName) } if len(caCerts) != 0 { t.Errorf("unexpected # of caCerts: got %d, want 0", len(caCerts)) } } var testdata = map[string]string{ // 'null' password test case "Windows Azure Tools": `MIIKDAIBAzCCCcwGCSqGSIb3DQEHAaCCCb0Eggm5MIIJtTCCBe4GCSqGSIb3DQEHAaCCBd8EggXbMIIF1zCCBdMGCyqGSIb3DQEMCgECoIIE7jCCBOowHAYKKoZIhvcNAQwBAzAOBAhStUNnlTGV+gICB9AEggTIJ81JIossF6boFWpPtkiQRPtI6DW6e9QD4/WvHAVrM2bKdpMzSMsCML5NyuddANTKHBVq00Jc9keqGNAqJPKkjhSUebzQFyhe0E1oI9T4zY5UKr/I8JclOeccH4QQnsySzYUG2SnniXnQ+JrG3juetli7EKth9h6jLc6xbubPadY5HMB3wL/eG/kJymiXwU2KQ9Mgd4X6jbcV+NNCE/8jbZHvSTCPeYTJIjxfeX61Sj5kFKUCzERbsnpyevhY3X0eYtEDezZQarvGmXtMMdzf8HJHkWRdk9VLDLgjk8uiJif/+X4FohZ37ig0CpgC2+dP4DGugaZZ51hb8tN9GeCKIsrmWogMXDIVd0OACBp/EjJVmFB6y0kUCXxUE0TZt0XA1tjAGJcjDUpBvTntZjPsnH/4ZySy+s2d9OOhJ6pzRQBRm360TzkFdSwk9DLiLdGfv4pwMMu/vNGBlqjP/1sQtj+jprJiD1sDbCl4AdQZVoMBQHadF2uSD4/o17XG/Ci0r2h6Htc2yvZMAbEY4zMjjIn2a+vqIxD6onexaek1R3zbkS9j19D6EN9EWn8xgz80YRCyW65znZk8xaIhhvlU/mg7sTxeyuqroBZNcq6uDaQTehDpyH7bY2l4zWRpoj10a6JfH2q5shYz8Y6UZC/kOTfuGqbZDNZWro/9pYquvNNW0M847E5t9bsf9VkAAMHRGBbWoVoU9VpI0UnoXSfvpOo+aXa2DSq5sHHUTVY7A9eov3z5IqT+pligx11xcs+YhDWcU8di3BTJisohKvv5Y8WSkm/rloiZd4ig269k0jTRk1olP/vCksPli4wKG2wdsd5o42nX1yL7mFfXocOANZbB+5qMkiwdyoQSk+Vq+C8nAZx2bbKhUq2MbrORGMzOe0Hh0x2a0PeObycN1Bpyv7Mp3ZI9h5hBnONKCnqMhtyQHUj/nNvbJUnDVYNfoOEqDiEqqEwB7YqWzAKz8KW0OIqdlM8uiQ4JqZZlFllnWJUfaiDrdFM3lYSnFQBkzeVlts6GpDOOBjCYd7dcCNS6kq6pZC6p6HN60Twu0JnurZD6RT7rrPkIGE8vAenFt4iGe/yF52fahCSY8Ws4K0UTwN7bAS+4xRHVCWvE8sMRZsRCHizb5laYsVrPZJhE6+hux6OBb6w8kwPYXc+ud5v6UxawUWgt6uPwl8mlAtU9Z7Miw4Nn/wtBkiLL/ke1UI1gqJtcQXgHxx6mzsjh41+nAgTvdbsSEyU6vfOmxGj3Rwc1eOrIhJUqn5YjOWfzzsz/D5DzWKmwXIwdspt1p+u+kol1N3f2wT9fKPnd/RGCb4g/1hc3Aju4DQYgGY782l89CEEdalpQ/35bQczMFk6Fje12HykakWEXd/bGm9Unh82gH84USiRpeOfQvBDYoqEyrY3zkFZzBjhDqa+jEcAj41tcGx47oSfDq3iVYCdL7HSIjtnyEktVXd7mISZLoMt20JACFcMw+mrbjlug+eU7o2GR7T+LwtOp/p4LZqyLa7oQJDwde1BNZtm3TCK2P1mW94QDL0nDUps5KLtr1DaZXEkRbjSJub2ZE9WqDHyU3KA8G84Tq/rN1IoNu/if45jacyPje1Npj9IftUZSP22nV7HMwZtwQ4P4MYHRMBMGCSqGSIb3DQEJFTEGBAQBAAAAMFsGCSqGSIb3DQEJFDFOHkwAewBCADQAQQA0AEYARQBCADAALQBBADEAOABBAC0ANAA0AEIAQgAtAEIANQBGADIALQA0ADkAMQBFAEYAMQA1ADIAQgBBADEANgB9MF0GCSsGAQQBgjcRATFQHk4ATQBpAGMAcgBvAHMAbwBmAHQAIABTAG8AZgB0AHcAYQByAGUAIABLAGUAeQAgAFMAdABvAHIAYQBnAGUAIABQAHIAbwB2AGkAZABlAHIwggO/BgkqhkiG9w0BBwagggOwMIIDrAIBADCCA6UGCSqGSIb3DQEHATAcBgoqhkiG9w0BDAEGMA4ECEBk5ZAYpu0WAgIH0ICCA3hik4mQFGpw9Ha8TQPtk+j2jwWdxfF0+sTk6S8PTsEfIhB7wPltjiCK92Uv2tCBQnodBUmatIfkpnRDEySmgmdglmOCzj204lWAMRs94PoALGn3JVBXbO1vIDCbAPOZ7Z0Hd0/1t2hmk8v3//QJGUg+qr59/4y/MuVfIg4qfkPcC2QSvYWcK3oTf6SFi5rv9B1IOWFgN5D0+C+x/9Lb/myPYX+rbOHrwtJ4W1fWKoz9g7wwmGFA9IJ2DYGuH8ifVFbDFT1Vcgsvs8arSX7oBsJVW0qrP7XkuDRe3EqCmKW7rBEwYrFznhxZcRDEpMwbFoSvgSIZ4XhFY9VKYglT+JpNH5iDceYEBOQL4vBLpxNUk3l5jKaBNxVa14AIBxq18bVHJ+STInhLhad4u10v/Xbx7wIL3f9DX1yLAkPrpBYbNHS2/ew6H/ySDJnoIDxkw2zZ4qJ+qUJZ1S0lbZVG+VT0OP5uF6tyOSpbMlcGkdl3z254n6MlCrTifcwkzscysDsgKXaYQw06rzrPW6RDub+t+hXzGny799fS9jhQMLDmOggaQ7+LA4oEZsfT89HLMWxJYDqjo3gIfjciV2mV54R684qLDS+AO09U49e6yEbwGlq8lpmO/pbXCbpGbB1b3EomcQbxdWxW2WEkkEd/VBn81K4M3obmywwXJkw+tPXDXfBmzzaqqCR+onMQ5ME1nMkY8ybnfoCc1bDIupjVWsEL2Wvq752RgI6KqzVNr1ew1IdqV5AWN2fOfek+0vi3Jd9FHF3hx8JMwjJL9dZsETV5kHtYJtE7wJ23J68BnCt2eI0GEuwXcCf5EdSKN/xXCTlIokc4Qk/gzRdIZsvcEJ6B1lGovKG54X4IohikqTjiepjbsMWj38yxDmK3mtENZ9ci8FPfbbvIEcOCZIinuY3qFUlRSbx7VUerEoV1IP3clUwexVQo4lHFee2jd7ocWsdSqSapW7OWUupBtDzRkqVhE7tGria+i1W2d6YLlJ21QTjyapWJehAMO637OdbJCCzDs1cXbodRRE7bsP492ocJy8OX66rKdhYbg8srSFNKdb3pF3UDNbN9jhI/t8iagRhNBhlQtTr1me2E/c86Q18qcRXl4bcXTt6acgCeffK6Y26LcVlrgjlD33AEYRRUeyC+rpxbT0aMjdFderlndKRIyG23mSp0HaUwNzAfMAcGBSsOAwIaBBRlviCbIyRrhIysg2dc/KbLFTc2vQQUg4rfwHMM4IKYRD/fsd1x6dda+wQ=`, // empty string password test case "testing@example.com": `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 HQ8CAggA`, } golang-sslmate-src-go-pkcs12-0.6.0/safebags.go000066400000000000000000000072461510447322700210430ustar00rootroot00000000000000// Copyright 2015, 2018, 2019 Opsmate, Inc. All rights reserved. // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package pkcs12 import ( "crypto/x509" "encoding/asn1" "errors" "io" ) var ( // see https://tools.ietf.org/html/rfc7292#appendix-D oidCertTypeX509Certificate = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 22, 1}) oidKeyBag = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 1}) oidPKCS8ShroundedKeyBag = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 2}) oidCertBag = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 3}) ) type certBag struct { Id asn1.ObjectIdentifier Data []byte `asn1:"tag:0,explicit"` } func decodePkcs8ShroudedKeyBag(asn1Data, password []byte) (privateKey interface{}, err error) { pkinfo := new(encryptedPrivateKeyInfo) if err = unmarshal(asn1Data, pkinfo); err != nil { return nil, errors.New("pkcs12: error decoding PKCS#8 shrouded key bag: " + err.Error()) } pkData, err := pbDecrypt(pkinfo, password) if err != nil { return nil, errors.New("pkcs12: error decrypting PKCS#8 shrouded key bag: " + err.Error()) } ret := new(asn1.RawValue) if err = unmarshal(pkData, ret); err != nil { return nil, errors.New("pkcs12: error unmarshaling decrypted private key: " + err.Error()) } if privateKey, err = x509.ParsePKCS8PrivateKey(pkData); err != nil { return nil, errors.New("pkcs12: error parsing PKCS#8 private key: " + err.Error()) } return privateKey, nil } func encodePkcs8ShroudedKeyBag(rand io.Reader, privateKey interface{}, algoID asn1.ObjectIdentifier, password []byte, iterations int, saltLen int) (asn1Data []byte, err error) { var pkData []byte if pkData, err = x509.MarshalPKCS8PrivateKey(privateKey); err != nil { return nil, errors.New("pkcs12: error encoding PKCS#8 private key: " + err.Error()) } randomSalt := make([]byte, saltLen) if _, err = rand.Read(randomSalt); err != nil { return nil, errors.New("pkcs12: error reading random salt: " + err.Error()) } var paramBytes []byte if algoID.Equal(oidPBES2) { if paramBytes, err = makePBES2Parameters(rand, randomSalt, iterations); err != nil { return nil, errors.New("pkcs12: error encoding params: " + err.Error()) } } else { if paramBytes, err = asn1.Marshal(pbeParams{Salt: randomSalt, Iterations: iterations}); err != nil { return nil, errors.New("pkcs12: error encoding params: " + err.Error()) } } var pkinfo encryptedPrivateKeyInfo pkinfo.AlgorithmIdentifier.Algorithm = algoID pkinfo.AlgorithmIdentifier.Parameters.FullBytes = paramBytes if err = pbEncrypt(&pkinfo, pkData, password); err != nil { return nil, errors.New("pkcs12: error encrypting PKCS#8 shrouded key bag: " + err.Error()) } if asn1Data, err = asn1.Marshal(pkinfo); err != nil { return nil, errors.New("pkcs12: error encoding PKCS#8 shrouded key bag: " + err.Error()) } return asn1Data, nil } func decodeCertBag(asn1Data []byte) (x509Certificates []byte, err error) { bag := new(certBag) if err := unmarshal(asn1Data, bag); err != nil { return nil, errors.New("pkcs12: error decoding cert bag: " + err.Error()) } if !bag.Id.Equal(oidCertTypeX509Certificate) { return nil, NotImplementedError("only X509 certificates are supported in cert bags") } return bag.Data, nil } func encodeCertBag(x509Certificates []byte) (asn1Data []byte, err error) { var bag certBag bag.Id = oidCertTypeX509Certificate bag.Data = x509Certificates if asn1Data, err = asn1.Marshal(bag); err != nil { return nil, errors.New("pkcs12: error encoding cert bag: " + err.Error()) } return asn1Data, nil } golang-sslmate-src-go-pkcs12-0.6.0/testdata/000077500000000000000000000000001510447322700205415ustar00rootroot00000000000000golang-sslmate-src-go-pkcs12-0.6.0/testdata/rfc9579-a1.txt000066400000000000000000000071151510447322700227150ustar00rootroot00000000000000MIIKigIBAzCCCgUGCSqGSIb3DQEHAaCCCfYEggnyMIIJ7jCCBGIGCSqGSIb3DQEH BqCCBFMwggRPAgEAMIIESAYJKoZIhvcNAQcBMFcGCSqGSIb3DQEFDTBKMCkGCSqG SIb3DQEFDDAcBAg9pxXxY2yscwICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQME ASoEEK7yYaFQDi1pYwWzm9F/fs+AggPgFIT2XapyaFgDppdvLkdvaF3HXw+zjzKb 7xFC76DtVPhVTWVHD+kIss+jsj+XyvMwY0aCuAhAG/Dig+vzWomnsqB5ssw5/kTb +TMQ5PXLkNeoBmB6ArKeGc/QmCBQvQG/a6b+nXSWmxNpP+71772dmWmB8gcSJ0kF Fj75NrIbmNiDMCb71Q8gOzBMFf6BpXf/3xWAJtxyic+tSNETfOJa8zTZb0+lV0w9 5eUmDrPUpuxEVbb0KJtIc63gRkcfrPtDd6Ii4Zzbzj2Evr4/S4hnrQBsiryVzJWy IEjaD0y6+DmG0JwMgRuGi1wBoGowi37GMrDCOyOZWC4n5wHLtYyhR6JaElxbrhxP H46z2USLKmZoF+YgEQgYcSBXMgP0t36+XQocFWYi2N5niy02TnctwF430FYsQlhJ Suma4I33E808dJuMv8T/soF66HsD4Zj46hOf4nWmas7IaoSAbGKXgIa7KhGRJvij xM3WOX0aqNi/8bhnxSA7fCmIy/7opyx5UYJFWGBSmHP1pBHBVmx7Ad8SAsB9MSsh nbGjGiUk4h0QcOi29/M9WwFlo4urePyI8PK2qtVAmpD3rTLlsmgzguZ69L0Q/CFU fbtqsMF0bgEuh8cfivd1DYFABEt1gypuwCUtCqQ7AXK2nQqOjsQCxVz9i9K8NDeD aau98VAl0To2sk3/VR/QUq0PRwU1jPN5BzUevhE7SOy/ImuJKwpGqqFljYdrQmj5 jDe+LmYH9QGVRlfN8zuU+48FY8CAoeBeHn5AAPml0PYPVUnt3/jQN1+v+CahNVI+ La8q1Nen+j1R44aa2I3y/pUgtzXRwK+tPrxTQbG030EU51LYJn8amPWmn3w75ZIA MJrXWeKj44de7u4zdUsEBVC2uM44rIHM8MFjyYAwYsey0rcp0emsaxzar+7ZA67r lDoXvvS3NqsnTXHcn3T9tkPRoee6L7Dh3x4Od96lcRwgdYT5BwyH7e34ld4VTUmJ bDEq7Ijvn4JKrwQJh1RCC+Z/ObfkC42xAm7G010u3g08xB0Qujpdg4a7VcuWrywF c7hLNquuaF4qoDaVwYXHH3iuX6YlJ/3siTKbYCVXPEZOAMBP9lF/OU76UMJBQNfU 0xjDx+3AhUVgnGuCsmYlK6ETDp8qOZKGyV0KrNSGtqLx3uMhd7PETeW+ML3tDQ/0 X9fMkcZHi4C2fXnoHV/qa2dGhBj4jjQ0Xh1poU6mxGn2Mebe2hDsBZkkBpnn7pK4 wP/VqXdQTwqEuvzGHLVFsCuADe40ZFBmtBrf70wG7ZkO8SUZ8Zz1IX3+S024g7yj QRev/6x6TtkwggWEBgkqhkiG9w0BBwGgggV1BIIFcTCCBW0wggVpBgsqhkiG9w0B DAoBAqCCBTEwggUtMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAhTxzw+ VptrYAICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEK9nSqc1I2t4tMVG bWHpdtQEggTQzCwI7j34gCTvfj6nuOSndAjShGv7mN2j7WMV0pslTpq2b9Bn3vn1 Y0JMvL4E7sLrUzNU02pdOcfCnEpMFccNv2sQrLp1mOCKxu8OjSqHZLoKVL0ROVsZ 8dMECLLigDlPKRiSyLErl14tErX4/zbkUaWMROO28kFbTbubQ8YoHlRUwsKW1xLg vfi0gRkG/zHXRfQHjX/8NStv7hXlehn7/Gy2EKPsRFhadm/iUHAfmCMkMgHTU248 JER9+nsXltd59H+IeDpj/kbxZ+YvHow9XUZKu828d3MQnUpLZ1BfJGhMBPVwbVUD A40CiQBVdCoGtPJyalL28xoS3H0ILFCnwQOr6u0HwleNJPGHq78HUyH6Hwxnh0b0 5o163r6wTFZn5cMOxpbs/Ttd+3TrxmrYpd2XnuRme3cnaYJ0ILvpc/8eLLR7SKjD T4JhZ0h/CfcV2WWvhpQugkY0pWrZ+EIMneB1dZB96mJVLxOi148OeSgi0PsxZMNi YM33rTpwQT5WqOsEyDwUQpne5b8Kkt/s7EN0LJNnPyJJRL1LcqOdr6j+6YqRtPa7 a9oWJqMcuTP+bqzGRJh+3HDlFBw2Yzp9iadv4KmB2MzhStLUoi2MSjvnnkkd5Led sshAd6WbKfF7kLAHQHT4Ai6dMEO4EKkEVF9JBtxCR4JEn6C98Lpg+Lk+rfY7gHOf ZxtgGURwgXRY3aLUrdT55ZKgk3ExVKPzi5EhdpAau7JKhpOwyKozAp/OKWMNrz6h obu2Mbn1B+IA60psYHHxynBgsJHv7WQmbYh8HyGfHgVvaA8pZCYqxxjpLjSJrR8B Bu9H9xkTh7KlhxgreXYv19uAYbUd95kcox9izad6VPnovgFSb+Omdy6PJACPj6hF W6PJbucP0YPpO0VtWtQdZZ3df1P0hZ7qvKwOPFA+gKZSckgqASfygiP9V3Zc8jIi wjNzoDM2QT+UUJKiiGYXJUEOO9hxzFHlGj759DcNRhpgl5AgR57ofISD9yBuCAJY PQ/aZHPFuRTrcVG3RaIbCAS73nEznKyFaLOXfzyfyaSmyhsH253tnyL1MejC+2bR Eko/yldgFUxvU5JI+Q3KJ6Awj+PnduHXx71E4UwSuu2xXYMpxnQwI6rroQpZBX82 HhqgcLV83P8lpzQwPdHjH5zkoxmWdC0+jU/tcQfNXYpJdyoaX7tDmVclLhwl9ps/ O841pIsNLJWXwvxG6B+3LN/kw4QjwN194PopiOD7+oDm5mhttO78CrBrRxHMD/0Q qniZjKzSZepxlZq+J792u8vtMnuzzChxu0Bf3PhIXcJNcVhwUtr0yKe/N+NvC0tm p8wyik/BlndxN9eKbdTOi2wIi64h2QG8nOk66wQ/PSIJYwZl6eDNEQSzH/1mGCfU QnUT17UC/p+Qgenf6Auap2GWlvsJrB7u/pytz65rtjt/ouo6Ih6EwWqwVVpGXZD0 7gVWH0Ke/Vr6aPGNvkLcmftPuDZsn9jiig3guhdeyRVf10Ox369kKWcG75q77hxE IzSzDyUlBNbnom9SIjut3r+qVYmWONatC6q/4D0I42Lnjd3dEyZx7jmH3g/S2ASM FzWr9pvXc61dsYOkdZ4PYa9XPUZxXFagZsoS3F1sU799+IJVU0tC0MExJTAjBgkq hkiG9w0BCRUxFgQUwWO5DorvVWYF3BWUmAw0rUEajScwfDBtMEkGCSqGSIb3DQEF DjA8MCwGCSqGSIb3DQEFDDAfBAhvRzw4sC4xcwICCAACASAwDAYIKoZIhvcNAgkF ADAMBggqhkiG9w0CCQUABCB6pW2FOdcCNj87zS64NUXG36K5aXDnFHctIk5Bf4kG 3QQITk9UIFVTRUQCAQE= golang-sslmate-src-go-pkcs12-0.6.0/testdata/rfc9579-a2.txt000066400000000000000000000071151510447322700227160ustar00rootroot00000000000000MIIKigIBAzCCCgUGCSqGSIb3DQEHAaCCCfYEggnyMIIJ7jCCBGIGCSqGSIb3DQEH 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 6QQITk9UIFVTRUQCAQE= golang-sslmate-src-go-pkcs12-0.6.0/testdata/rfc9579-a3.txt000066400000000000000000000071711510447322700227210ustar00rootroot00000000000000MIIKrAIBAzCCCgUGCSqGSIb3DQEHAaCCCfYEggnyMIIJ7jCCBGIGCSqGSIb3DQEH BqCCBFMwggRPAgEAMIIESAYJKoZIhvcNAQcBMFcGCSqGSIb3DQEFDTBKMCkGCSqG SIb3DQEFDDAcBAisrqL8obSBaQICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQME ASoEECjXYYca0pwsgn1Imb9WqFGAggPgT7RcF5YzEJANZU9G3tSdpCHnyWatTlhm iCEcBGgwI5gz0+GoX+JCojgYY4g+KxeqznyCu+6GeD00T4Em7SWme9nzAfBFzng0 3lYCSnahSEKfgHerbzAtq9kgXkclPVk0Liy92/buf0Mqotjjs/5o78AqP86Pwbj8 xYNuXOU1ivO0JiW2c2HefKYvUvMYlOh99LCoZPLHPkaaZ4scAwDjFeTICU8oowVk LKvslrg1pHbfmXHMFJ4yqub37hRtj2CoJNy4+UA2hBYlBi9WnuAJIsjv0qS3kpLe 4+J2DGe31GNG8pD01XD0l69OlailK1ykh4ap2u0KeD2z357+trCFbpWMMXQcSUCO OcVjxYqgv/l1++9huOHoPSt224x4wZfJ7cO2zbAAx/K2CPhdvi4CBaDHADsRq/c8 SAi+LX5SCocGT51zL5KQD6pnr2ExaVum+U8a3nMPPMv9R2MfFUksYNGgFvS+lcZf R3qk/G9iXtSgray0mwRA8pWzoXl43vc9HJuuCU+ryOc/h36NChhQ9ltivUNaiUc2 b9AAQSrZD8Z7KtxjbH3noS+gjDtimDB0Uh199zaCwQ95y463zdYsNCESm1OT979o Y+81BWFMFM/Hog5s7Ynhoi2E9+ZlyLK2UeKwvWjGzvcdPvxHR+5l/h6PyWROlpaZ zmzZBm+NKmbXtMD2AEa5+Q32ZqJQhijXZyIji3NS65y81j/a1ZrvU0lOVKA+MSPN KU27/eKZuF1LEL6qaazTUmpznLLdaVQy5aZ1qz5dyCziKcuHIclhh+RCblHU6XdE 6pUTZSRQQiGUIkPUTnU9SFlZc7VwvxgeynLyXPCSzOKNWYGajy1LxDvv28uhMgNd WF51bNkl1QYl0fNunGO7YFt4wk+g7CQ/Yu2w4P7S3ZLMw0g4eYclcvyIMt4vxXfp VTKIPyzMqLr+0dp1eCPm8fIdaBZUhMUC/OVqLwgnPNY9cXCrn2R1cGKo5LtvtjbH 2skz/D5DIOErfZSBJ8LE3De4j8MAjOeC8ia8LaM4PNfW/noQP1LBsZtTDTqEy01N Z5uliIocyQzlyWChErJv/Wxh+zBpbk1iXc2Owmh2GKjx0VSe7XbiqdoKkONUNUIE siseASiU/oXdJYUnBYVEUDJ1HPz7qnKiFhSgxNJZnoPfzbbx1hEzV+wxQqNnWIqQ U0s7Jt22wDBzPBHGao2tnGRLuBZWVePJGbsxThGKwrf3vYsNJTxme5KJiaxcPMwE r+ln2AqVOzzXHXgIxv/dvK0Qa7pH3AvGzcFjQChTRipgqiRrLor0//8580h+Ly2l IFo7bCuztmcwggWEBgkqhkiG9w0BBwGgggV1BIIFcTCCBW0wggVpBgsqhkiG9w0B DAoBAqCCBTEwggUtMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAi1c7S5 IEG77wICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEN6rzRtIdYxqOnY+ aDS3AFYEggTQNdwUoZDXCryOFBUI/z71vfoyAxlnwJLRHNXQUlI7w0KkH22aNnSm xiaXHoCP1HgcmsYORS7p/ITi/9atCHqnGR4zHmePNhoMpNHFehdjlUUWgt004vUJ 5ZwTdXweM+K4We6CfWA/tyvsyGNAsuunel+8243Zsv0mGLKpjA+ZyALt51s0knmX OD2DW49FckImUVnNC5LmvEIAmVC/ZNycryZQI+2EBkJKe+BC3834GexJnSwtUBg3 Xg33ZV7X66kw8tK1Ws5zND5GQAJyIu47mnjZkIWQBY+XbWowrBZ8uXIQuxMZC0p8 u62oIAtZaVQoVTR1LyR/7PISFW6ApwtbTn6uQxsb16qF8lEM0S1+x0AfJY6Zm11t yCqbb2tYZF+X34MoUkR/IYC/KCq/KJdpnd8Yqgfrwjg8dR2WGIxbp2GBHq6BK/DI ehOLMcLcsOuP0DEXppfcelMOGNIs+4h4KsjWiHVDMPsqLdozBdm6FLGcno3lY5FO +avVrlElAOB+9evgaBbD2lSrEMoOjAoD090tgXXwYBEnWnIpdk+56cf5IpshrLBA /+H13LBLes+X1o5dd0Mu+3abp5RtAv7zLPRRtXkDYJPzgNcTvJ2Wxw2C+zrAclzZ 7IRdcLESUa4CsN01aEvQgOtkCNVjSCtkJGP0FstsWM4hP7lfSB7P2tDL+ugy6GvB X1sz9fMC7QMAFL98nDm/yqcnejG1BcQXZho8n0svSfbcVByGlPZGMuI9t25+0B2M TAx0f6zoD8+fFmhcVgS6MQPybGKFawckYl0zulsePqs+G4voIW17owGKsRiv06Jm ZSwd3KoGmjM49ADzuG9yrQ5PSa0nhVk1tybNape4HNYHrAmmN0ILlN+E0Bs/Edz4 ntYZuoc/Z35tCgm79dV4/Vl6HUZ1JrLsLrEWCByVytwVFyf3/MwTWdf+Ac+XzBuC yEMqPlvnPWswdnaid35pxios79fPl1Hr0/Q6+DoA5GyYq8SFdP7EYLrGMGa5GJ+x 5nS7z6U4UmZ2sXuKYHnuhB0zi6Y04a+fhT71x02eTeC7aPlEB319UqysujJVJnso bkcwOu/Jj0Is9YeFd693dB44xeZuYyvlwoD19lqcim0TSa2Tw7D1W/yu47dKrVP2 VKxRqomuAQOpoZiuSfq1/7ysrV8U4hIlIU2vnrSVJ8EtPQKsoBW5l70dQGwXyxBk BUTHqfJ4LG/kPGRMOtUzgqFw2DjJtbym1q1MZgp2ycMon4vp7DeQLGs2XfEANB+Y nRwtjpevqAnIuK6K3Y02LY4FXTNQpC37Xb04bmdIQAcE0MaoP4/hY87aS82PQ68g 3bI79uKo4we2g+WaEJlEzQ7147ZzV2wbDq89W69x1MWTfaDwlEtd4UaacYchAv7B TVaaVFiRAUywWaHGePpZG2WV1feH/zd+temxWR9qMFgBZySg1jipBPVciwl0LqlW s/raIBYmLmAaMMgM3759UkNVznDoFHrY4z2EADXp0RHHVzJS1x+yYvp/9I+AcW55 oN0UP/3uQ6eyz/ix22sovQwhMJ8rmgR6CfyRPKmXu1RPK3puNv7mbFTfTXpYN2vX vhEZReXY8hJF/9o4G3UrJ1F0MgUHMCG86cw1z0bhPSaXVoufOnx/fRoxJTAjBgkq hkiG9w0BCRUxFgQUwWO5DorvVWYF3BWUmAw0rUEajScwgZ0wgY0wSQYJKoZIhvcN AQUOMDwwLAYJKoZIhvcNAQUMMB8ECFDaXOUaOcUPAgIIAAIBQDAMBggqhkiG9w0C CwUAMAwGCCqGSIb3DQILBQAEQHIAM8C9OAsHUCj9CmOJioqf7YwD4O/b3UiZ3Wqo F6OmQIRDc68SdkZJ6024l4nWlnhTE7a4lb2Tru4k3NOTa1oECE5PVCBVU0VEAgEB golang-sslmate-src-go-pkcs12-0.6.0/testdata/rfc9579-a4.txt000066400000000000000000000071151510447322700227200ustar00rootroot00000000000000MIIKiwIBAzCCCgUGCSqGSIb3DQEHAaCCCfYEggnyMIIJ7jCCBGIGCSqGSIb3DQEH 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 3QQITk9UIFVTRUQCAggA golang-sslmate-src-go-pkcs12-0.6.0/testdata/rfc9579-a5.txt000066400000000000000000000071151510447322700227210ustar00rootroot00000000000000MIIKigIBAzCCCgUGCSqGSIb3DQEHAaCCCfYEggnyMIIJ7jCCBGIGCSqGSIb3DQEH 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 3QQIb0c8OLAuMXMCAQE= golang-sslmate-src-go-pkcs12-0.6.0/testdata/rfc9579-a6.txt000066400000000000000000000071111510447322700227160ustar00rootroot00000000000000MIIKiAIBAzCCCgUGCSqGSIb3DQEHAaCCCfYEggnyMIIJ7jCCBGIGCSqGSIb3DQEH BqCCBFMwggRPAgEAMIIESAYJKoZIhvcNAQcBMFcGCSqGSIb3DQEFDTBKMCkGCSqG SIb3DQEFDDAcBAg9pxXxY2yscwICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQME ASoEEK7yYaFQDi1pYwWzm9F/fs+AggPgFIT2XapyaFgDppdvLkdvaF3HXw+zjzKb 7xFC76DtVPhVTWVHD+kIss+jsj+XyvMwY0aCuAhAG/Dig+vzWomnsqB5ssw5/kTb +TMQ5PXLkNeoBmB6ArKeGc/QmCBQvQG/a6b+nXSWmxNpP+71772dmWmB8gcSJ0kF Fj75NrIbmNiDMCb71Q8gOzBMFf6BpXf/3xWAJtxyic+tSNETfOJa8zTZb0+lV0w9 5eUmDrPUpuxEVbb0KJtIc63gRkcfrPtDd6Ii4Zzbzj2Evr4/S4hnrQBsiryVzJWy IEjaD0y6+DmG0JwMgRuGi1wBoGowi37GMrDCOyOZWC4n5wHLtYyhR6JaElxbrhxP H46z2USLKmZoF+YgEQgYcSBXMgP0t36+XQocFWYi2N5niy02TnctwF430FYsQlhJ Suma4I33E808dJuMv8T/soF66HsD4Zj46hOf4nWmas7IaoSAbGKXgIa7KhGRJvij xM3WOX0aqNi/8bhnxSA7fCmIy/7opyx5UYJFWGBSmHP1pBHBVmx7Ad8SAsB9MSsh nbGjGiUk4h0QcOi29/M9WwFlo4urePyI8PK2qtVAmpD3rTLlsmgzguZ69L0Q/CFU fbtqsMF0bgEuh8cfivd1DYFABEt1gypuwCUtCqQ7AXK2nQqOjsQCxVz9i9K8NDeD aau98VAl0To2sk3/VR/QUq0PRwU1jPN5BzUevhE7SOy/ImuJKwpGqqFljYdrQmj5 jDe+LmYH9QGVRlfN8zuU+48FY8CAoeBeHn5AAPml0PYPVUnt3/jQN1+v+CahNVI+ La8q1Nen+j1R44aa2I3y/pUgtzXRwK+tPrxTQbG030EU51LYJn8amPWmn3w75ZIA MJrXWeKj44de7u4zdUsEBVC2uM44rIHM8MFjyYAwYsey0rcp0emsaxzar+7ZA67r lDoXvvS3NqsnTXHcn3T9tkPRoee6L7Dh3x4Od96lcRwgdYT5BwyH7e34ld4VTUmJ bDEq7Ijvn4JKrwQJh1RCC+Z/ObfkC42xAm7G010u3g08xB0Qujpdg4a7VcuWrywF c7hLNquuaF4qoDaVwYXHH3iuX6YlJ/3siTKbYCVXPEZOAMBP9lF/OU76UMJBQNfU 0xjDx+3AhUVgnGuCsmYlK6ETDp8qOZKGyV0KrNSGtqLx3uMhd7PETeW+ML3tDQ/0 X9fMkcZHi4C2fXnoHV/qa2dGhBj4jjQ0Xh1poU6mxGn2Mebe2hDsBZkkBpnn7pK4 wP/VqXdQTwqEuvzGHLVFsCuADe40ZFBmtBrf70wG7ZkO8SUZ8Zz1IX3+S024g7yj QRev/6x6TtkwggWEBgkqhkiG9w0BBwGgggV1BIIFcTCCBW0wggVpBgsqhkiG9w0B DAoBAqCCBTEwggUtMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAhTxzw+ VptrYAICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEK9nSqc1I2t4tMVG bWHpdtQEggTQzCwI7j34gCTvfj6nuOSndAjShGv7mN2j7WMV0pslTpq2b9Bn3vn1 Y0JMvL4E7sLrUzNU02pdOcfCnEpMFccNv2sQrLp1mOCKxu8OjSqHZLoKVL0ROVsZ 8dMECLLigDlPKRiSyLErl14tErX4/zbkUaWMROO28kFbTbubQ8YoHlRUwsKW1xLg vfi0gRkG/zHXRfQHjX/8NStv7hXlehn7/Gy2EKPsRFhadm/iUHAfmCMkMgHTU248 JER9+nsXltd59H+IeDpj/kbxZ+YvHow9XUZKu828d3MQnUpLZ1BfJGhMBPVwbVUD A40CiQBVdCoGtPJyalL28xoS3H0ILFCnwQOr6u0HwleNJPGHq78HUyH6Hwxnh0b0 5o163r6wTFZn5cMOxpbs/Ttd+3TrxmrYpd2XnuRme3cnaYJ0ILvpc/8eLLR7SKjD T4JhZ0h/CfcV2WWvhpQugkY0pWrZ+EIMneB1dZB96mJVLxOi148OeSgi0PsxZMNi YM33rTpwQT5WqOsEyDwUQpne5b8Kkt/s7EN0LJNnPyJJRL1LcqOdr6j+6YqRtPa7 a9oWJqMcuTP+bqzGRJh+3HDlFBw2Yzp9iadv4KmB2MzhStLUoi2MSjvnnkkd5Led sshAd6WbKfF7kLAHQHT4Ai6dMEO4EKkEVF9JBtxCR4JEn6C98Lpg+Lk+rfY7gHOf ZxtgGURwgXRY3aLUrdT55ZKgk3ExVKPzi5EhdpAau7JKhpOwyKozAp/OKWMNrz6h obu2Mbn1B+IA60psYHHxynBgsJHv7WQmbYh8HyGfHgVvaA8pZCYqxxjpLjSJrR8B Bu9H9xkTh7KlhxgreXYv19uAYbUd95kcox9izad6VPnovgFSb+Omdy6PJACPj6hF W6PJbucP0YPpO0VtWtQdZZ3df1P0hZ7qvKwOPFA+gKZSckgqASfygiP9V3Zc8jIi wjNzoDM2QT+UUJKiiGYXJUEOO9hxzFHlGj759DcNRhpgl5AgR57ofISD9yBuCAJY PQ/aZHPFuRTrcVG3RaIbCAS73nEznKyFaLOXfzyfyaSmyhsH253tnyL1MejC+2bR Eko/yldgFUxvU5JI+Q3KJ6Awj+PnduHXx71E4UwSuu2xXYMpxnQwI6rroQpZBX82 HhqgcLV83P8lpzQwPdHjH5zkoxmWdC0+jU/tcQfNXYpJdyoaX7tDmVclLhwl9ps/ O841pIsNLJWXwvxG6B+3LN/kw4QjwN194PopiOD7+oDm5mhttO78CrBrRxHMD/0Q qniZjKzSZepxlZq+J792u8vtMnuzzChxu0Bf3PhIXcJNcVhwUtr0yKe/N+NvC0tm p8wyik/BlndxN9eKbdTOi2wIi64h2QG8nOk66wQ/PSIJYwZl6eDNEQSzH/1mGCfU QnUT17UC/p+Qgenf6Auap2GWlvsJrB7u/pytz65rtjt/ouo6Ih6EwWqwVVpGXZD0 7gVWH0Ke/Vr6aPGNvkLcmftPuDZsn9jiig3guhdeyRVf10Ox369kKWcG75q77hxE IzSzDyUlBNbnom9SIjut3r+qVYmWONatC6q/4D0I42Lnjd3dEyZx7jmH3g/S2ASM FzWr9pvXc61dsYOkdZ4PYa9XPUZxXFagZsoS3F1sU799+IJVU0tC0MExJTAjBgkq hkiG9w0BCRUxFgQUwWO5DorvVWYF3BWUmAw0rUEajScwejBqMEYGCSqGSIb3DQEF DjA5MCkGCSqGSIb3DQEFDDAcBAhvRzw4sC4xcwICCAAwDAYIKoZIhvcNAgkFADAM BggqhkiG9w0CCQUABCB6pW2FOdcCNj87zS64NUXG36K5aXDnFHctIk5Bf4kG3QQI b0c8OLAuMXMCAggA