go mod vendor
+ move k8s.io/apimachinery fork from go.work to go.mod (and include it in vendor)
This commit is contained in:
		
							
								
								
									
										23
									
								
								vendor/github.com/youmark/pkcs8/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/youmark/pkcs8/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| # Compiled Object files, Static and Dynamic libs (Shared Objects) | ||||
| *.o | ||||
| *.a | ||||
| *.so | ||||
|  | ||||
| # Folders | ||||
| _obj | ||||
| _test | ||||
|  | ||||
| # Architecture specific extensions/prefixes | ||||
| *.[568vq] | ||||
| [568vq].out | ||||
|  | ||||
| *.cgo1.go | ||||
| *.cgo2.c | ||||
| _cgo_defun.c | ||||
| _cgo_gotypes.go | ||||
| _cgo_export.* | ||||
|  | ||||
| _testmain.go | ||||
|  | ||||
| *.exe | ||||
| *.test | ||||
							
								
								
									
										14
									
								
								vendor/github.com/youmark/pkcs8/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								vendor/github.com/youmark/pkcs8/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| arch: | ||||
|     - amd64 | ||||
|     - ppc64le | ||||
| language: go | ||||
|  | ||||
| go: | ||||
|   - "1.10.x" | ||||
|   - "1.11.x" | ||||
|   - "1.12.x" | ||||
|   - "1.13.x" | ||||
|   - master | ||||
|  | ||||
| script: | ||||
|   - go test -v ./... | ||||
							
								
								
									
										21
									
								
								vendor/github.com/youmark/pkcs8/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/youmark/pkcs8/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| The MIT License (MIT) | ||||
|  | ||||
| Copyright (c) 2014 youmark | ||||
|  | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
|  | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
|  | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
							
								
								
									
										1
									
								
								vendor/github.com/youmark/pkcs8/README
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/youmark/pkcs8/README
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| pkcs8 package: implement PKCS#8 private key parsing and conversion as defined in RFC5208 and RFC5958 | ||||
							
								
								
									
										22
									
								
								vendor/github.com/youmark/pkcs8/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/youmark/pkcs8/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| pkcs8 | ||||
| === | ||||
| OpenSSL can generate private keys in both "traditional format" and PKCS#8 format. Newer applications are advised to use more secure PKCS#8 format. Go standard crypto package provides a [function](http://golang.org/pkg/crypto/x509/#ParsePKCS8PrivateKey) to parse private key in PKCS#8 format. There is a limitation to this function. It can only handle unencrypted PKCS#8 private keys. To use this function, the user has to save the private key in file without encryption, which is a bad practice to leave private keys unprotected on file systems. In addition, Go standard package lacks the functions to convert RSA/ECDSA private keys into PKCS#8 format. | ||||
|  | ||||
| pkcs8 package fills the gap here. It implements functions to process private keys in PKCS#8 format, as defined in [RFC5208](https://tools.ietf.org/html/rfc5208) and [RFC5958](https://tools.ietf.org/html/rfc5958). It can handle both unencrypted PKCS#8 PrivateKeyInfo format and EncryptedPrivateKeyInfo format with PKCS#5 (v2.0) algorithms. | ||||
|  | ||||
|  | ||||
| [**Godoc**](http://godoc.org/github.com/youmark/pkcs8) | ||||
|  | ||||
| ## Installation | ||||
| Supports Go 1.10+. Release v1.1 is the last release supporting Go 1.9  | ||||
|  | ||||
| ```text | ||||
| go get github.com/youmark/pkcs8 | ||||
| ``` | ||||
| ## dependency | ||||
| This package depends on golang.org/x/crypto/pbkdf2 and golang.org/x/crypto/scrypt packages. Use the following command to retrieve them | ||||
| ```text | ||||
| go get golang.org/x/crypto/pbkdf2 | ||||
| go get golang.org/x/crypto/scrypt | ||||
| ``` | ||||
|  | ||||
							
								
								
									
										60
									
								
								vendor/github.com/youmark/pkcs8/cipher.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								vendor/github.com/youmark/pkcs8/cipher.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| package pkcs8 | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"crypto/cipher" | ||||
| 	"encoding/asn1" | ||||
| ) | ||||
|  | ||||
| type cipherWithBlock struct { | ||||
| 	oid      asn1.ObjectIdentifier | ||||
| 	ivSize   int | ||||
| 	keySize  int | ||||
| 	newBlock func(key []byte) (cipher.Block, error) | ||||
| } | ||||
|  | ||||
| func (c cipherWithBlock) IVSize() int { | ||||
| 	return c.ivSize | ||||
| } | ||||
|  | ||||
| func (c cipherWithBlock) KeySize() int { | ||||
| 	return c.keySize | ||||
| } | ||||
|  | ||||
| func (c cipherWithBlock) OID() asn1.ObjectIdentifier { | ||||
| 	return c.oid | ||||
| } | ||||
|  | ||||
| func (c cipherWithBlock) Encrypt(key, iv, plaintext []byte) ([]byte, error) { | ||||
| 	block, err := c.newBlock(key) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return cbcEncrypt(block, key, iv, plaintext) | ||||
| } | ||||
|  | ||||
| func (c cipherWithBlock) Decrypt(key, iv, ciphertext []byte) ([]byte, error) { | ||||
| 	block, err := c.newBlock(key) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return cbcDecrypt(block, key, iv, ciphertext) | ||||
| } | ||||
|  | ||||
| func cbcEncrypt(block cipher.Block, key, iv, plaintext []byte) ([]byte, error) { | ||||
| 	mode := cipher.NewCBCEncrypter(block, iv) | ||||
| 	paddingLen := block.BlockSize() - (len(plaintext) % block.BlockSize()) | ||||
| 	ciphertext := make([]byte, len(plaintext)+paddingLen) | ||||
| 	copy(ciphertext, plaintext) | ||||
| 	copy(ciphertext[len(plaintext):], bytes.Repeat([]byte{byte(paddingLen)}, paddingLen)) | ||||
| 	mode.CryptBlocks(ciphertext, ciphertext) | ||||
| 	return ciphertext, nil | ||||
| } | ||||
|  | ||||
| func cbcDecrypt(block cipher.Block, key, iv, ciphertext []byte) ([]byte, error) { | ||||
| 	mode := cipher.NewCBCDecrypter(block, iv) | ||||
| 	plaintext := make([]byte, len(ciphertext)) | ||||
| 	mode.CryptBlocks(plaintext, ciphertext) | ||||
| 	// TODO: remove padding | ||||
| 	return plaintext, nil | ||||
| } | ||||
							
								
								
									
										24
									
								
								vendor/github.com/youmark/pkcs8/cipher_3des.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								vendor/github.com/youmark/pkcs8/cipher_3des.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| package pkcs8 | ||||
|  | ||||
| import ( | ||||
| 	"crypto/des" | ||||
| 	"encoding/asn1" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	oidDESEDE3CBC = asn1.ObjectIdentifier{1, 2, 840, 113549, 3, 7} | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	RegisterCipher(oidDESEDE3CBC, func() Cipher { | ||||
| 		return TripleDESCBC | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // TripleDESCBC is the 168-bit key 3DES cipher in CBC mode. | ||||
| var TripleDESCBC = cipherWithBlock{ | ||||
| 	ivSize:   des.BlockSize, | ||||
| 	keySize:  24, | ||||
| 	newBlock: des.NewTripleDESCipher, | ||||
| 	oid:      oidDESEDE3CBC, | ||||
| } | ||||
							
								
								
									
										84
									
								
								vendor/github.com/youmark/pkcs8/cipher_aes.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								vendor/github.com/youmark/pkcs8/cipher_aes.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| package pkcs8 | ||||
|  | ||||
| import ( | ||||
| 	"crypto/aes" | ||||
| 	"encoding/asn1" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	oidAES128CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 2} | ||||
| 	oidAES128GCM = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 6} | ||||
| 	oidAES192CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 22} | ||||
| 	oidAES192GCM = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 26} | ||||
| 	oidAES256CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 42} | ||||
| 	oidAES256GCM = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 46} | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	RegisterCipher(oidAES128CBC, func() Cipher { | ||||
| 		return AES128CBC | ||||
| 	}) | ||||
| 	RegisterCipher(oidAES128GCM, func() Cipher { | ||||
| 		return AES128GCM | ||||
| 	}) | ||||
| 	RegisterCipher(oidAES192CBC, func() Cipher { | ||||
| 		return AES192CBC | ||||
| 	}) | ||||
| 	RegisterCipher(oidAES192GCM, func() Cipher { | ||||
| 		return AES192GCM | ||||
| 	}) | ||||
| 	RegisterCipher(oidAES256CBC, func() Cipher { | ||||
| 		return AES256CBC | ||||
| 	}) | ||||
| 	RegisterCipher(oidAES256GCM, func() Cipher { | ||||
| 		return AES256GCM | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // AES128CBC is the 128-bit key AES cipher in CBC mode. | ||||
| var AES128CBC = cipherWithBlock{ | ||||
| 	ivSize:   aes.BlockSize, | ||||
| 	keySize:  16, | ||||
| 	newBlock: aes.NewCipher, | ||||
| 	oid:      oidAES128CBC, | ||||
| } | ||||
|  | ||||
| // AES128GCM is the 128-bit key AES cipher in GCM mode. | ||||
| var AES128GCM = cipherWithBlock{ | ||||
| 	ivSize:   aes.BlockSize, | ||||
| 	keySize:  16, | ||||
| 	newBlock: aes.NewCipher, | ||||
| 	oid:      oidAES128GCM, | ||||
| } | ||||
|  | ||||
| // AES192CBC is the 192-bit key AES cipher in CBC mode. | ||||
| var AES192CBC = cipherWithBlock{ | ||||
| 	ivSize:   aes.BlockSize, | ||||
| 	keySize:  24, | ||||
| 	newBlock: aes.NewCipher, | ||||
| 	oid:      oidAES192CBC, | ||||
| } | ||||
|  | ||||
| // AES192GCM is the 912-bit key AES cipher in GCM mode. | ||||
| var AES192GCM = cipherWithBlock{ | ||||
| 	ivSize:   aes.BlockSize, | ||||
| 	keySize:  24, | ||||
| 	newBlock: aes.NewCipher, | ||||
| 	oid:      oidAES192GCM, | ||||
| } | ||||
|  | ||||
| // AES256CBC is the 256-bit key AES cipher in CBC mode. | ||||
| var AES256CBC = cipherWithBlock{ | ||||
| 	ivSize:   aes.BlockSize, | ||||
| 	keySize:  32, | ||||
| 	newBlock: aes.NewCipher, | ||||
| 	oid:      oidAES256CBC, | ||||
| } | ||||
|  | ||||
| // AES256GCM is the 256-bit key AES cipher in GCM mode. | ||||
| var AES256GCM = cipherWithBlock{ | ||||
| 	ivSize:   aes.BlockSize, | ||||
| 	keySize:  32, | ||||
| 	newBlock: aes.NewCipher, | ||||
| 	oid:      oidAES256GCM, | ||||
| } | ||||
							
								
								
									
										91
									
								
								vendor/github.com/youmark/pkcs8/kdf_pbkdf2.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								vendor/github.com/youmark/pkcs8/kdf_pbkdf2.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | ||||
| package pkcs8 | ||||
|  | ||||
| import ( | ||||
| 	"crypto" | ||||
| 	"crypto/sha1" | ||||
| 	"crypto/sha256" | ||||
| 	"crypto/x509/pkix" | ||||
| 	"encoding/asn1" | ||||
| 	"errors" | ||||
| 	"hash" | ||||
|  | ||||
| 	"golang.org/x/crypto/pbkdf2" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	oidPKCS5PBKDF2        = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 12} | ||||
| 	oidHMACWithSHA1       = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 7} | ||||
| 	oidHMACWithSHA256     = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 9} | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	RegisterKDF(oidPKCS5PBKDF2, func() KDFParameters { | ||||
| 		return new(pbkdf2Params) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func newHashFromPRF(ai pkix.AlgorithmIdentifier) (func() hash.Hash, error) { | ||||
| 	switch { | ||||
| 	case len(ai.Algorithm) == 0 || ai.Algorithm.Equal(oidHMACWithSHA1): | ||||
| 		return sha1.New, nil | ||||
| 	case ai.Algorithm.Equal(oidHMACWithSHA256): | ||||
| 		return sha256.New, nil | ||||
| 	default: | ||||
| 		return nil, errors.New("pkcs8: unsupported hash function") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func newPRFParamFromHash(h crypto.Hash) (pkix.AlgorithmIdentifier, error) { | ||||
| 	switch h { | ||||
| 	case crypto.SHA1: | ||||
| 		return pkix.AlgorithmIdentifier{ | ||||
| 			Algorithm:  oidHMACWithSHA1, | ||||
| 			Parameters: asn1.RawValue{Tag: asn1.TagNull}}, nil | ||||
| 	case crypto.SHA256: | ||||
| 		return pkix.AlgorithmIdentifier{ | ||||
| 			Algorithm:  oidHMACWithSHA256, | ||||
| 			Parameters: asn1.RawValue{Tag: asn1.TagNull}}, nil | ||||
| 	} | ||||
| 	return pkix.AlgorithmIdentifier{}, errors.New("pkcs8: unsupported hash function") | ||||
| } | ||||
|  | ||||
| type pbkdf2Params struct { | ||||
| 	Salt           []byte | ||||
| 	IterationCount int | ||||
| 	PRF            pkix.AlgorithmIdentifier `asn1:"optional"` | ||||
| } | ||||
|  | ||||
| func (p pbkdf2Params) DeriveKey(password []byte, size int) (key []byte, err error) { | ||||
| 	h, err := newHashFromPRF(p.PRF) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return pbkdf2.Key(password, p.Salt, p.IterationCount, size, h), nil | ||||
| } | ||||
|  | ||||
| // PBKDF2Opts contains options for the PBKDF2 key derivation function. | ||||
| type PBKDF2Opts struct { | ||||
| 	SaltSize       int | ||||
| 	IterationCount int | ||||
| 	HMACHash       crypto.Hash | ||||
| } | ||||
|  | ||||
| func (p PBKDF2Opts) DeriveKey(password, salt []byte, size int) ( | ||||
| 	key []byte, params KDFParameters, err error) { | ||||
|  | ||||
| 	key = pbkdf2.Key(password, salt, p.IterationCount, size, p.HMACHash.New) | ||||
| 	prfParam, err := newPRFParamFromHash(p.HMACHash) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	params = pbkdf2Params{salt, p.IterationCount, prfParam} | ||||
| 	return key, params, nil | ||||
| } | ||||
|  | ||||
| func (p PBKDF2Opts) GetSaltSize() int { | ||||
| 	return p.SaltSize | ||||
| } | ||||
|  | ||||
| func (p PBKDF2Opts) OID() asn1.ObjectIdentifier { | ||||
| 	return oidPKCS5PBKDF2 | ||||
| } | ||||
							
								
								
									
										62
									
								
								vendor/github.com/youmark/pkcs8/kdf_scrypt.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								vendor/github.com/youmark/pkcs8/kdf_scrypt.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| package pkcs8 | ||||
|  | ||||
| import ( | ||||
| 	"encoding/asn1" | ||||
|  | ||||
| 	"golang.org/x/crypto/scrypt" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	oidScrypt = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11591, 4, 11} | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	RegisterKDF(oidScrypt, func() KDFParameters { | ||||
| 		return new(scryptParams) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| type scryptParams struct { | ||||
| 	Salt                     []byte | ||||
| 	CostParameter            int | ||||
| 	BlockSize                int | ||||
| 	ParallelizationParameter int | ||||
| } | ||||
|  | ||||
| func (p scryptParams) DeriveKey(password []byte, size int) (key []byte, err error) { | ||||
| 	return scrypt.Key(password, p.Salt, p.CostParameter, p.BlockSize, | ||||
| 		p.ParallelizationParameter, size) | ||||
| } | ||||
|  | ||||
| // ScryptOpts contains options for the scrypt key derivation function. | ||||
| type ScryptOpts struct { | ||||
| 	SaltSize                 int | ||||
| 	CostParameter            int | ||||
| 	BlockSize                int | ||||
| 	ParallelizationParameter int | ||||
| } | ||||
|  | ||||
| func (p ScryptOpts) DeriveKey(password, salt []byte, size int) ( | ||||
| 	key []byte, params KDFParameters, err error) { | ||||
|  | ||||
| 	key, err = scrypt.Key(password, salt, p.CostParameter, p.BlockSize, | ||||
| 		p.ParallelizationParameter, size) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	params = scryptParams{ | ||||
| 		BlockSize:                p.BlockSize, | ||||
| 		CostParameter:            p.CostParameter, | ||||
| 		ParallelizationParameter: p.ParallelizationParameter, | ||||
| 		Salt:                     salt, | ||||
| 	} | ||||
| 	return key, params, nil | ||||
| } | ||||
|  | ||||
| func (p ScryptOpts) GetSaltSize() int { | ||||
| 	return p.SaltSize | ||||
| } | ||||
|  | ||||
| func (p ScryptOpts) OID() asn1.ObjectIdentifier { | ||||
| 	return oidScrypt | ||||
| } | ||||
							
								
								
									
										309
									
								
								vendor/github.com/youmark/pkcs8/pkcs8.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										309
									
								
								vendor/github.com/youmark/pkcs8/pkcs8.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,309 @@ | ||||
| // Package pkcs8 implements functions to parse and convert private keys in PKCS#8 format, as defined in RFC5208 and RFC5958 | ||||
| package pkcs8 | ||||
|  | ||||
| import ( | ||||
| 	"crypto" | ||||
| 	"crypto/ecdsa" | ||||
| 	"crypto/rand" | ||||
| 	"crypto/rsa" | ||||
| 	"crypto/x509" | ||||
| 	"crypto/x509/pkix" | ||||
| 	"encoding/asn1" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| ) | ||||
|  | ||||
| // DefaultOpts are the default options for encrypting a key if none are given. | ||||
| // The defaults can be changed by the library user. | ||||
| var DefaultOpts = &Opts{ | ||||
| 	Cipher: AES256CBC, | ||||
| 	KDFOpts: PBKDF2Opts{ | ||||
| 		SaltSize:       8, | ||||
| 		IterationCount: 10000, | ||||
| 		HMACHash:       crypto.SHA256, | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| // KDFOpts contains options for a key derivation function. | ||||
| // An implementation of this interface must be specified when encrypting a PKCS#8 key. | ||||
| type KDFOpts interface { | ||||
| 	// DeriveKey derives a key of size bytes from the given password and salt. | ||||
| 	// It returns the key and the ASN.1-encodable parameters used. | ||||
| 	DeriveKey(password, salt []byte, size int) (key []byte, params KDFParameters, err error) | ||||
| 	// GetSaltSize returns the salt size specified. | ||||
| 	GetSaltSize() int | ||||
| 	// OID returns the OID of the KDF specified. | ||||
| 	OID() asn1.ObjectIdentifier | ||||
| } | ||||
|  | ||||
| // KDFParameters contains parameters (salt, etc.) for a key deriviation function. | ||||
| // It must be a ASN.1-decodable structure. | ||||
| // An implementation of this interface is created when decoding an encrypted PKCS#8 key. | ||||
| type KDFParameters interface { | ||||
| 	// DeriveKey derives a key of size bytes from the given password. | ||||
| 	// It uses the salt from the decoded parameters. | ||||
| 	DeriveKey(password []byte, size int) (key []byte, err error) | ||||
| } | ||||
|  | ||||
| var kdfs = make(map[string]func() KDFParameters) | ||||
|  | ||||
| // RegisterKDF registers a function that returns a new instance of the given KDF | ||||
| // parameters. This allows the library to support client-provided KDFs. | ||||
| func RegisterKDF(oid asn1.ObjectIdentifier, params func() KDFParameters) { | ||||
| 	kdfs[oid.String()] = params | ||||
| } | ||||
|  | ||||
| // Cipher represents a cipher for encrypting the key material. | ||||
| type Cipher interface { | ||||
| 	// IVSize returns the IV size of the cipher, in bytes. | ||||
| 	IVSize() int | ||||
| 	// KeySize returns the key size of the cipher, in bytes. | ||||
| 	KeySize() int | ||||
| 	// Encrypt encrypts the key material. | ||||
| 	Encrypt(key, iv, plaintext []byte) ([]byte, error) | ||||
| 	// Decrypt decrypts the key material. | ||||
| 	Decrypt(key, iv, ciphertext []byte) ([]byte, error) | ||||
| 	// OID returns the OID of the cipher specified. | ||||
| 	OID() asn1.ObjectIdentifier | ||||
| } | ||||
|  | ||||
| var ciphers = make(map[string]func() Cipher) | ||||
|  | ||||
| // RegisterCipher registers a function that returns a new instance of the given | ||||
| // cipher. This allows the library to support client-provided ciphers. | ||||
| func RegisterCipher(oid asn1.ObjectIdentifier, cipher func() Cipher) { | ||||
| 	ciphers[oid.String()] = cipher | ||||
| } | ||||
|  | ||||
| // Opts contains options for encrypting a PKCS#8 key. | ||||
| type Opts struct { | ||||
| 	Cipher  Cipher | ||||
| 	KDFOpts KDFOpts | ||||
| } | ||||
|  | ||||
| // Unecrypted PKCS8 | ||||
| var ( | ||||
| 	oidPBES2 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 13} | ||||
| ) | ||||
|  | ||||
| type encryptedPrivateKeyInfo struct { | ||||
| 	EncryptionAlgorithm pkix.AlgorithmIdentifier | ||||
| 	EncryptedData       []byte | ||||
| } | ||||
|  | ||||
| type pbes2Params struct { | ||||
| 	KeyDerivationFunc pkix.AlgorithmIdentifier | ||||
| 	EncryptionScheme  pkix.AlgorithmIdentifier | ||||
| } | ||||
|  | ||||
| type privateKeyInfo struct { | ||||
| 	Version             int | ||||
| 	PrivateKeyAlgorithm pkix.AlgorithmIdentifier | ||||
| 	PrivateKey          []byte | ||||
| } | ||||
|  | ||||
| func parseKeyDerivationFunc(keyDerivationFunc pkix.AlgorithmIdentifier) (KDFParameters, error) { | ||||
| 	oid := keyDerivationFunc.Algorithm.String() | ||||
| 	newParams, ok := kdfs[oid] | ||||
| 	if !ok { | ||||
| 		return nil, fmt.Errorf("pkcs8: unsupported KDF (OID: %s)", oid) | ||||
| 	} | ||||
| 	params := newParams() | ||||
| 	_, err := asn1.Unmarshal(keyDerivationFunc.Parameters.FullBytes, params) | ||||
| 	if err != nil { | ||||
| 		return nil, errors.New("pkcs8: invalid KDF parameters") | ||||
| 	} | ||||
| 	return params, nil | ||||
| } | ||||
|  | ||||
| func parseEncryptionScheme(encryptionScheme pkix.AlgorithmIdentifier) (Cipher, []byte, error) { | ||||
| 	oid := encryptionScheme.Algorithm.String() | ||||
| 	newCipher, ok := ciphers[oid] | ||||
| 	if !ok { | ||||
| 		return nil, nil, fmt.Errorf("pkcs8: unsupported cipher (OID: %s)", oid) | ||||
| 	} | ||||
| 	cipher := newCipher() | ||||
| 	var iv []byte | ||||
| 	if _, err := asn1.Unmarshal(encryptionScheme.Parameters.FullBytes, &iv); err != nil { | ||||
| 		return nil, nil, errors.New("pkcs8: invalid cipher parameters") | ||||
| 	} | ||||
| 	return cipher, iv, nil | ||||
| } | ||||
|  | ||||
| // ParsePrivateKey parses a DER-encoded PKCS#8 private key. | ||||
| // Password can be nil. | ||||
| // This is equivalent to ParsePKCS8PrivateKey. | ||||
| func ParsePrivateKey(der []byte, password []byte) (interface{}, KDFParameters, error) { | ||||
| 	// No password provided, assume the private key is unencrypted | ||||
| 	if len(password) == 0 { | ||||
| 		privateKey, err := x509.ParsePKCS8PrivateKey(der) | ||||
| 		return privateKey, nil, err | ||||
| 	} | ||||
|  | ||||
| 	// Use the password provided to decrypt the private key | ||||
| 	var privKey encryptedPrivateKeyInfo | ||||
| 	if _, err := asn1.Unmarshal(der, &privKey); err != nil { | ||||
| 		return nil, nil, errors.New("pkcs8: only PKCS #5 v2.0 supported") | ||||
| 	} | ||||
|  | ||||
| 	if !privKey.EncryptionAlgorithm.Algorithm.Equal(oidPBES2) { | ||||
| 		return nil, nil, errors.New("pkcs8: only PBES2 supported") | ||||
| 	} | ||||
|  | ||||
| 	var params pbes2Params | ||||
| 	if _, err := asn1.Unmarshal(privKey.EncryptionAlgorithm.Parameters.FullBytes, ¶ms); err != nil { | ||||
| 		return nil, nil, errors.New("pkcs8: invalid PBES2 parameters") | ||||
| 	} | ||||
|  | ||||
| 	cipher, iv, err := parseEncryptionScheme(params.EncryptionScheme) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
|  | ||||
| 	kdfParams, err := parseKeyDerivationFunc(params.KeyDerivationFunc) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
|  | ||||
| 	keySize := cipher.KeySize() | ||||
| 	symkey, err := kdfParams.DeriveKey(password, keySize) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
|  | ||||
| 	encryptedKey := privKey.EncryptedData | ||||
| 	decryptedKey, err := cipher.Decrypt(symkey, iv, encryptedKey) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
|  | ||||
| 	key, err := x509.ParsePKCS8PrivateKey(decryptedKey) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, errors.New("pkcs8: incorrect password") | ||||
| 	} | ||||
| 	return key, kdfParams, nil | ||||
| } | ||||
|  | ||||
| // MarshalPrivateKey encodes a private key into DER-encoded PKCS#8 with the given options. | ||||
| // Password can be nil. | ||||
| func MarshalPrivateKey(priv interface{}, password []byte, opts *Opts) ([]byte, error) { | ||||
| 	if len(password) == 0 { | ||||
| 		return x509.MarshalPKCS8PrivateKey(priv) | ||||
| 	} | ||||
|  | ||||
| 	if opts == nil { | ||||
| 		opts = DefaultOpts | ||||
| 	} | ||||
|  | ||||
| 	// Convert private key into PKCS8 format | ||||
| 	pkey, err := x509.MarshalPKCS8PrivateKey(priv) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	encAlg := opts.Cipher | ||||
| 	salt := make([]byte, opts.KDFOpts.GetSaltSize()) | ||||
| 	_, err = rand.Read(salt) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	iv := make([]byte, encAlg.IVSize()) | ||||
| 	_, err = rand.Read(iv) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	key, kdfParams, err := opts.KDFOpts.DeriveKey(password, salt, encAlg.KeySize()) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	encryptedKey, err := encAlg.Encrypt(key, iv, pkey) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	marshalledParams, err := asn1.Marshal(kdfParams) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	keyDerivationFunc := pkix.AlgorithmIdentifier{ | ||||
| 		Algorithm:  opts.KDFOpts.OID(), | ||||
| 		Parameters: asn1.RawValue{FullBytes: marshalledParams}, | ||||
| 	} | ||||
| 	marshalledIV, err := asn1.Marshal(iv) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	encryptionScheme := pkix.AlgorithmIdentifier{ | ||||
| 		Algorithm:  encAlg.OID(), | ||||
| 		Parameters: asn1.RawValue{FullBytes: marshalledIV}, | ||||
| 	} | ||||
|  | ||||
| 	encryptionAlgorithmParams := pbes2Params{ | ||||
| 		EncryptionScheme:  encryptionScheme, | ||||
| 		KeyDerivationFunc: keyDerivationFunc, | ||||
| 	} | ||||
| 	marshalledEncryptionAlgorithmParams, err := asn1.Marshal(encryptionAlgorithmParams) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	encryptionAlgorithm := pkix.AlgorithmIdentifier{ | ||||
| 		Algorithm:  oidPBES2, | ||||
| 		Parameters: asn1.RawValue{FullBytes: marshalledEncryptionAlgorithmParams}, | ||||
| 	} | ||||
|  | ||||
| 	encryptedPkey := encryptedPrivateKeyInfo{ | ||||
| 		EncryptionAlgorithm: encryptionAlgorithm, | ||||
| 		EncryptedData:       encryptedKey, | ||||
| 	} | ||||
|  | ||||
| 	return asn1.Marshal(encryptedPkey) | ||||
| } | ||||
|  | ||||
| // ParsePKCS8PrivateKey parses encrypted/unencrypted private keys in PKCS#8 format. To parse encrypted private keys, a password of []byte type should be provided to the function as the second parameter. | ||||
| func ParsePKCS8PrivateKey(der []byte, v ...[]byte) (interface{}, error) { | ||||
| 	var password []byte | ||||
| 	if len(v) > 0 { | ||||
| 		password = v[0] | ||||
| 	} | ||||
| 	privateKey, _, err := ParsePrivateKey(der, password) | ||||
| 	return privateKey, err | ||||
| } | ||||
|  | ||||
| // ParsePKCS8PrivateKeyRSA parses encrypted/unencrypted private keys in PKCS#8 format. To parse encrypted private keys, a password of []byte type should be provided to the function as the second parameter. | ||||
| func ParsePKCS8PrivateKeyRSA(der []byte, v ...[]byte) (*rsa.PrivateKey, error) { | ||||
| 	key, err := ParsePKCS8PrivateKey(der, v...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	typedKey, ok := key.(*rsa.PrivateKey) | ||||
| 	if !ok { | ||||
| 		return nil, errors.New("key block is not of type RSA") | ||||
| 	} | ||||
| 	return typedKey, nil | ||||
| } | ||||
|  | ||||
| // ParsePKCS8PrivateKeyECDSA parses encrypted/unencrypted private keys in PKCS#8 format. To parse encrypted private keys, a password of []byte type should be provided to the function as the second parameter. | ||||
| func ParsePKCS8PrivateKeyECDSA(der []byte, v ...[]byte) (*ecdsa.PrivateKey, error) { | ||||
| 	key, err := ParsePKCS8PrivateKey(der, v...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	typedKey, ok := key.(*ecdsa.PrivateKey) | ||||
| 	if !ok { | ||||
| 		return nil, errors.New("key block is not of type ECDSA") | ||||
| 	} | ||||
| 	return typedKey, nil | ||||
| } | ||||
|  | ||||
| // ConvertPrivateKeyToPKCS8 converts the private key into PKCS#8 format. | ||||
| // To encrypt the private key, the password of []byte type should be provided as the second parameter. | ||||
| // | ||||
| // The only supported key types are RSA and ECDSA (*rsa.PrivateKey or *ecdsa.PrivateKey for priv) | ||||
| func ConvertPrivateKeyToPKCS8(priv interface{}, v ...[]byte) ([]byte, error) { | ||||
| 	var password []byte | ||||
| 	if len(v) > 0 { | ||||
| 		password = v[0] | ||||
| 	} | ||||
| 	return MarshalPrivateKey(priv, password, nil) | ||||
| } | ||||
		Reference in New Issue
	
	Block a user