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