pax_global_header00006660000000000000000000000064147735724620014533gustar00rootroot0000000000000052 comment=52e1c804a67b4a21143923bb77196bd3bb8da948 golang-sslmate-src-go-pkcs12-0.5.0/000077500000000000000000000000001477357246200167435ustar00rootroot00000000000000golang-sslmate-src-go-pkcs12-0.5.0/.gitattributes000066400000000000000000000005311477357246200216350ustar00rootroot00000000000000# 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.5.0/.gitignore000066400000000000000000000001241477357246200207300ustar00rootroot00000000000000# Add no patterns to .hgignore except for files generated by the build. last-change golang-sslmate-src-go-pkcs12-0.5.0/LICENSE000066400000000000000000000030111477357246200177430ustar00rootroot00000000000000Copyright (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.5.0/README.md000066400000000000000000000023061477357246200202230ustar00rootroot00000000000000# 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.5.0/bmp-string.go000066400000000000000000000033341477357246200213570ustar00rootroot00000000000000// 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.5.0/bmp-string_test.go000066400000000000000000000040401477357246200224110ustar00rootroot00000000000000// 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.5.0/crypto.go000066400000000000000000000241251477357246200206160ustar00rootroot00000000000000// 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.Equal(asn1.ObjectIdentifier([]int{})): 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.5.0/crypto_test.go000066400000000000000000000121621477357246200216530ustar00rootroot00000000000000// 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.5.0/errors.go000066400000000000000000000013571477357246200206140ustar00rootroot00000000000000// 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.5.0/go.mod000066400000000000000000000001441477357246200200500ustar00rootroot00000000000000module software.sslmate.com/src/go-pkcs12 go 1.19 require golang.org/x/crypto v0.11.0 // indirect golang-sslmate-src-go-pkcs12-0.5.0/go.sum000066400000000000000000000037551477357246200201100ustar00rootroot00000000000000golang.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.5.0/internal/000077500000000000000000000000001477357246200205575ustar00rootroot00000000000000golang-sslmate-src-go-pkcs12-0.5.0/internal/rc2/000077500000000000000000000000001477357246200212455ustar00rootroot00000000000000golang-sslmate-src-go-pkcs12-0.5.0/internal/rc2/bench_test.go000066400000000000000000000010571477357246200237150ustar00rootroot00000000000000// 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.5.0/internal/rc2/rc2.go000066400000000000000000000142721477357246200222700ustar00rootroot00000000000000// 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.5.0/internal/rc2/rc2_test.go000066400000000000000000000030761477357246200233270ustar00rootroot00000000000000// 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.5.0/mac.go000066400000000000000000000040031477357246200200270ustar00rootroot00000000000000// 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" "hash" ) type macData struct { Mac digestInfo MacSalt []byte Iterations int `asn1:"optional,default:1"` } // from PKCS#7: type digestInfo struct { Algorithm pkix.AlgorithmIdentifier Digest []byte } 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}) ) func doMac(macData *macData, message, password []byte) ([]byte, error) { 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.5.0/mac_test.go000066400000000000000000000040621477357246200210730ustar00rootroot00000000000000// 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" "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) } } golang-sslmate-src-go-pkcs12-0.5.0/pbkdf.go000066400000000000000000000134671477357246200203730ustar00rootroot00000000000000// 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.5.0/pbkdf_test.go000066400000000000000000000025131477357246200214200ustar00rootroot00000000000000// 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.5.0/pkcs12.go000066400000000000000000000774171477357246200204150ustar00rootroot00000000000000// 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.5.0/pkcs12_test.go000066400000000000000000000610321477357246200214360ustar00rootroot00000000000000// 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": `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`, // empty string password test case "testing@example.com": `MIIJzgIBAzCCCZQGCSqGSIb3DQEHAaCCCYUEggmBMIIJfTCCA/cGCSqGSIb3DQEHBqCCA+gwggPk AgEAMIID3QYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQIIszfRGqcmPcCAggAgIIDsOZ9Eg1L s5Wx8JhYoV3HAL4aRnkAWvTYB5NISZOgSgIQTssmt/3A7134dibTmaT/93LikkL3cTKLnQzJ4wDf YZ1bprpVJvUqz+HFT79m27bP9zYXFrvxWBJbxjYKTSjQMgz+h8LAEpXXGajCmxMJ1oCOtdXkhhzc LdZN6SAYgtmtyFnCdMEDskSggGuLb3fw84QEJ/Sj6FAULXunW/CPaS7Ce0TMsKmNU/jfFWj3yXXw ro0kwjKiVLpVFlnBlHo2OoVU7hmkm59YpGhLgS7nxLD3n7nBroQ0ID1+8R01NnV9XLGoGzxMm1te 6UyTCkr5mj+kEQ8EP1Ys7g/TC411uhVWySMt/rcpkx7Vz1r9kYEAzJpONAfr6cuEVkPKrxpq4Fh0 2fzlKBky0i/hrfIEUmngh+ERHUb/Mtv/fkv1j5w9suESbhsMLLiCXAlsP1UWMX+3bNizi3WVMEts FM2k9byn+p8IUD/A8ULlE4kEaWeoc+2idkCNQkLGuIdGUXUFVm58se0auUkVRoRJx8x4CkMesT8j b1H831W66YRWoEwwDQp2kK1lA2vQXxdVHWlFevMNxJeromLzj3ayiaFrfByeUXhR2S+Hpm+c0yNR 4UVU9WED2kacsZcpRm9nlEa5sr28mri5JdBrNa/K02OOhvKCxr5ZGmbOVzUQKla2z4w+Ku9k8POm dfDNU/fGx1b5hcFWtghXe3msWVsSJrQihnN6q1ughzNiYZlJUGcHdZDRtiWwCFI0bR8h/Dmg9uO9 4rawQQrjIRT7B8yF3UbkZyAqs8Ppb1TsMeNPHh1rxEfGVQknh/48ouJYsmtbnzugTUt3mJCXXiL+ XcPMV6bBVAUu4aaVKSmg9+yJtY4/VKv10iw88ktv29fViIdBe3t6l/oPuvQgbQ8dqf4T8w0l/uKZ 9lS1Na9jfT1vCoS7F5TRi+tmyj1vL5kr/amEIW6xKEP6oeAMvCMtbPAzVEj38zdJ1R22FfuIBxkh f0Zl7pdVbmzRxl/SBx9iIBJSqAvcXItiT0FIj8HxQ+0iZKqMQMiBuNWJf5pYOLWGrIyntCWwHuaQ wrx0sTGuEL9YXLEAsBDrsvzLkx/56E4INGZFrH8G7HBdW6iGqb22IMI4GHltYSyBRKbB0gadYTyv abPEoqww8o7/85aPSzOTJ/53ozD438Q+d0u9SyDuOb60SzCD/zPuCEd78YgtXJwBYTuUNRT27FaM 3LGMX8Hz+6yPNRnmnA2XKPn7dx/IlaqAjIs8MIIFfgYJKoZIhvcNAQcBoIIFbwSCBWswggVnMIIF YwYLKoZIhvcNAQwKAQKgggTuMIIE6jAcBgoqhkiG9w0BDAEDMA4ECJr0cClYqOlcAgIIAASCBMhe OQSiP2s0/46ONXcNeVAkz2ksW3u/+qorhSiskGZ0b3dFa1hhgBU2Q7JVIkc4Hf7OXaT1eVQ8oqND uhqsNz83/kqYo70+LS8Hocj49jFgWAKrf/yQkdyP1daHa2yzlEw4mkpqOfnIORQHvYCa8nEApspZ wVu8y6WVuLHKU67mel7db2xwstQp7PRuSAYqGjTfAylElog8ASdaqqYbYIrCXucF8iF9oVgmb/Qo xrXshJ9aSLO4MuXlTPELmWgj07AXKSb90FKNihE+y0bWb9LPVFY1Sly3AX9PfrtkSXIZwqW3phpv MxGxQl/R6mr1z+hlTfY9Wdpb5vlKXPKA0L0Rt8d2pOesylFi6esJoS01QgP1kJILjbrV731kvDc0 Jsd+Oxv4BMwA7ClG8w1EAOInc/GrV1MWFGw/HeEqj3CZ/l/0jv9bwkbVeVCiIhoL6P6lVx9pXq4t KZ0uKg/tk5TVJmG2vLcMLvezD0Yk3G2ZOMrywtmskrwoF7oAUpO9e87szoH6fEvUZlkDkPVW1NV4 cZk3DBSQiuA3VOOg8qbo/tx/EE3H59P0axZWno2GSB0wFPWd1aj+b//tJEJHaaNR6qPRj4IWj9ru Qbc8eRAcVWleHg8uAehSvUXlFpyMQREyrnpvMGddpiTC8N4UMrrBRhV7+UbCOWhxPCbItnInBqgl 1JpSZIP7iUtsIMdu3fEC2cdbXMTRul+4rdzUR7F9OaezV3jjvcAbDvgbK1CpyC+MJ1Mxm/iTgk9V iUArydhlR8OniN84GyGYoYCW9O/KUwb6ASmeFOu/msx8x6kAsSQHIkKqMKv0TUR3kZnkxUvdpBGP KTl4YCTvNGX4dYALBqrAETRDhua2KVBD/kEttDHwBNVbN2xi81+Mc7ml461aADfk0c66R/m2sjHB 2tN9+wG12OIWFQjL6wF/UfJMYamxx2zOOExiId29Opt57uYiNVLOO4ourPewHPeH0u8Gz35aero7 lkt7cZAe1Q0038JUuE/QGlnK4lESK9UkSIQAjSaAlTsrcfwtQxB2EjoOoLhwH5mvxUEmcNGNnXUc 9xj3M5BD3zBz3Ft7G3YMMDwB1+zC2l+0UG0MGVjMVaeoy32VVNvxgX7jk22OXG1iaOB+PY9kdk+O X+52BGSf/rD6X0EnqY7XuRPkMGgjtpZeAYxRQnFtCZgDY4wYheuxqSSpdF49yNczSPLkgB3CeCfS +9NTKN7aC6hBbmW/8yYh6OvSiCEwY0lFS/T+7iaVxr1loE4zI1y/FFp4Pe1qfLlLttVlkygga2UU SCunTQ8UB/M5IXWKkhMOO11dP4niWwb39Y7pCWpau7mwbXOKfRPX96cgHnQJK5uG+BesDD1oYnX0 6frN7FOnTSHKruRIwuI8KnOQ/I+owmyz71wiv5LMQt+yM47UrEjB/EZa5X8dpEwOZvkdqL7utcyo l0XH5kWMXdW856LL/FYftAqJIDAmtX1TXF/rbP6mPyN/IlDC0gjP84Uzd/a2UyTIWr+wk49Ek3vQ /uDamq6QrwAxVmNh5Tset5Vhpc1e1kb7mRMZIzxSP8JcTuYd45oFKi98I8YjvueHVZce1g7OudQP SbFQoJvdT46iBg1TTatlltpOiH2mFaxWVS0xYjAjBgkqhkiG9w0BCRUxFgQUdA9eVqvETX4an/c8 p8SsTugkit8wOwYJKoZIhvcNAQkUMS4eLABGAHIAaQBlAG4AZABsAHkAIABuAGEAbQBlACAAZgBv AHIAIABjAGUAcgB0MDEwITAJBgUrDgMCGgUABBRFsNz3Zd1O1GI8GTuFwCWuDOjEEwQIuBEfIcAy HQ8CAggA`, } golang-sslmate-src-go-pkcs12-0.5.0/safebags.go000066400000000000000000000072461477357246200210560ustar00rootroot00000000000000// 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 }