mirror of
https://github.com/rclone/rclone.git
synced 2024-11-25 09:41:44 +08:00
vendor: add pkcs8 helpers for decrypting encrypted private keys
This commit is contained in:
parent
1031bcfc5a
commit
643192b347
1
go.mod
1
go.mod
|
@ -53,6 +53,7 @@ require (
|
|||
github.com/stretchr/testify v1.4.0
|
||||
github.com/t3rm1n4l/go-mega v0.0.0-20190528125457-55e675378686
|
||||
github.com/xanzy/ssh-agent v0.2.1
|
||||
github.com/youmark/pkcs8 v0.0.0-20181201043747-70daafe5d78a
|
||||
github.com/yunify/qingstor-sdk-go/v3 v3.0.2
|
||||
go.etcd.io/bbolt v1.3.3 // indirect
|
||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586
|
||||
|
|
2
go.sum
2
go.sum
|
@ -234,6 +234,8 @@ github.com/willf/bitset v1.1.9/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPyS
|
|||
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
|
||||
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181201043747-70daafe5d78a h1:wRlvyDgRuJOLgD2vcuBUbEduzTkcN7quLip1EnX/Dl4=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181201043747-70daafe5d78a/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||
github.com/yunify/qingstor-sdk-go/v3 v3.0.2 h1:2pL3tEj6eEESsHKrqsLZ5D+OkHEhYfsW1xwYRcHCgZs=
|
||||
github.com/yunify/qingstor-sdk-go/v3 v3.0.2/go.mod h1:KciFNuMu6F4WLk9nGwwK69sCGKLCdd9f97ac/wfumS4=
|
||||
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
|
||||
|
|
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
|
9
vendor/github.com/youmark/pkcs8/.travis.yml
generated
vendored
Normal file
9
vendor/github.com/youmark/pkcs8/.travis.yml
generated
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
language: go
|
||||
|
||||
go:
|
||||
- "1.9.x"
|
||||
- "1.10.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
|
21
vendor/github.com/youmark/pkcs8/README.md
generated
vendored
Normal file
21
vendor/github.com/youmark/pkcs8/README.md
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
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.9+
|
||||
|
||||
```text
|
||||
go get github.com/youmark/pkcs8
|
||||
```
|
||||
## dependency
|
||||
This package depends on golang.org/x/crypto/pbkdf2 package. Use the following command to retrive pbkdf2 package
|
||||
```text
|
||||
go get golang.org/x/crypto/pbkdf2
|
||||
```
|
||||
|
308
vendor/github.com/youmark/pkcs8/pkcs8.go
generated
vendored
Normal file
308
vendor/github.com/youmark/pkcs8/pkcs8.go
generated
vendored
Normal file
|
@ -0,0 +1,308 @@
|
|||
// Package pkcs8 implements functions to parse and convert private keys in PKCS#8 format, as defined in RFC5208 and RFC5958
|
||||
package pkcs8
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/des"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"encoding/asn1"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/crypto/pbkdf2"
|
||||
)
|
||||
|
||||
// Copy from crypto/x509
|
||||
var (
|
||||
oidPublicKeyRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
|
||||
oidPublicKeyDSA = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 1}
|
||||
oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
|
||||
)
|
||||
|
||||
// Copy from crypto/x509
|
||||
var (
|
||||
oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33}
|
||||
oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7}
|
||||
oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34}
|
||||
oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35}
|
||||
)
|
||||
|
||||
// Copy from crypto/x509
|
||||
func oidFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) {
|
||||
switch curve {
|
||||
case elliptic.P224():
|
||||
return oidNamedCurveP224, true
|
||||
case elliptic.P256():
|
||||
return oidNamedCurveP256, true
|
||||
case elliptic.P384():
|
||||
return oidNamedCurveP384, true
|
||||
case elliptic.P521():
|
||||
return oidNamedCurveP521, true
|
||||
}
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Unecrypted PKCS8
|
||||
var (
|
||||
oidPKCS5PBKDF2 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 12}
|
||||
oidPBES2 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 13}
|
||||
oidAES256CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 42}
|
||||
oidAES128CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 2}
|
||||
oidHMACWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 9}
|
||||
oidDESEDE3CBC = asn1.ObjectIdentifier{1, 2, 840, 113549, 3, 7}
|
||||
)
|
||||
|
||||
type ecPrivateKey struct {
|
||||
Version int
|
||||
PrivateKey []byte
|
||||
NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"`
|
||||
PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"`
|
||||
}
|
||||
|
||||
type privateKeyInfo struct {
|
||||
Version int
|
||||
PrivateKeyAlgorithm []asn1.ObjectIdentifier
|
||||
PrivateKey []byte
|
||||
}
|
||||
|
||||
// Encrypted PKCS8
|
||||
type prfParam struct {
|
||||
IdPRF asn1.ObjectIdentifier
|
||||
NullParam asn1.RawValue
|
||||
}
|
||||
|
||||
type pbkdf2Params struct {
|
||||
Salt []byte
|
||||
IterationCount int
|
||||
PrfParam prfParam `asn1:"optional"`
|
||||
}
|
||||
|
||||
type pbkdf2Algorithms struct {
|
||||
IdPBKDF2 asn1.ObjectIdentifier
|
||||
PBKDF2Params pbkdf2Params
|
||||
}
|
||||
|
||||
type pbkdf2Encs struct {
|
||||
EncryAlgo asn1.ObjectIdentifier
|
||||
IV []byte
|
||||
}
|
||||
|
||||
type pbes2Params struct {
|
||||
KeyDerivationFunc pbkdf2Algorithms
|
||||
EncryptionScheme pbkdf2Encs
|
||||
}
|
||||
|
||||
type pbes2Algorithms struct {
|
||||
IdPBES2 asn1.ObjectIdentifier
|
||||
PBES2Params pbes2Params
|
||||
}
|
||||
|
||||
type encryptedPrivateKeyInfo struct {
|
||||
EncryptionAlgorithm pbes2Algorithms
|
||||
EncryptedData []byte
|
||||
}
|
||||
|
||||
// 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.
|
||||
//
|
||||
// The function can decrypt the private key encrypted with AES-256-CBC mode, and stored in PKCS #5 v2.0 format.
|
||||
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.
|
||||
//
|
||||
// The function can decrypt the private key encrypted with AES-256-CBC mode, and stored in PKCS #5 v2.0 format.
|
||||
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
|
||||
}
|
||||
|
||||
// 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.
|
||||
//
|
||||
// The function can decrypt the private key encrypted with AES-256-CBC mode, and stored in PKCS #5 v2.0 format.
|
||||
func ParsePKCS8PrivateKey(der []byte, v ...[]byte) (interface{}, error) {
|
||||
// No password provided, assume the private key is unencrypted
|
||||
if v == nil {
|
||||
return x509.ParsePKCS8PrivateKey(der)
|
||||
}
|
||||
|
||||
// Use the password provided to decrypt the private key
|
||||
password := v[0]
|
||||
var privKey encryptedPrivateKeyInfo
|
||||
if _, err := asn1.Unmarshal(der, &privKey); err != nil {
|
||||
return nil, errors.New("pkcs8: only PKCS #5 v2.0 supported")
|
||||
}
|
||||
|
||||
if !privKey.EncryptionAlgorithm.IdPBES2.Equal(oidPBES2) {
|
||||
return nil, errors.New("pkcs8: only PBES2 supported")
|
||||
}
|
||||
|
||||
if !privKey.EncryptionAlgorithm.PBES2Params.KeyDerivationFunc.IdPBKDF2.Equal(oidPKCS5PBKDF2) {
|
||||
return nil, errors.New("pkcs8: only PBKDF2 supported")
|
||||
}
|
||||
|
||||
encParam := privKey.EncryptionAlgorithm.PBES2Params.EncryptionScheme
|
||||
kdfParam := privKey.EncryptionAlgorithm.PBES2Params.KeyDerivationFunc.PBKDF2Params
|
||||
|
||||
iv := encParam.IV
|
||||
salt := kdfParam.Salt
|
||||
iter := kdfParam.IterationCount
|
||||
keyHash := sha1.New
|
||||
if kdfParam.PrfParam.IdPRF.Equal(oidHMACWithSHA256) {
|
||||
keyHash = sha256.New
|
||||
}
|
||||
|
||||
encryptedKey := privKey.EncryptedData
|
||||
var symkey []byte
|
||||
var block cipher.Block
|
||||
var err error
|
||||
switch {
|
||||
case encParam.EncryAlgo.Equal(oidAES128CBC):
|
||||
symkey = pbkdf2.Key(password, salt, iter, 16, keyHash)
|
||||
block, err = aes.NewCipher(symkey)
|
||||
case encParam.EncryAlgo.Equal(oidAES256CBC):
|
||||
symkey = pbkdf2.Key(password, salt, iter, 32, keyHash)
|
||||
block, err = aes.NewCipher(symkey)
|
||||
case encParam.EncryAlgo.Equal(oidDESEDE3CBC):
|
||||
symkey = pbkdf2.Key(password, salt, iter, 24, keyHash)
|
||||
block, err = des.NewTripleDESCipher(symkey)
|
||||
default:
|
||||
return nil, errors.New("pkcs8: only AES-256-CBC, AES-128-CBC and DES-EDE3-CBC are supported")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mode := cipher.NewCBCDecrypter(block, iv)
|
||||
mode.CryptBlocks(encryptedKey, encryptedKey)
|
||||
|
||||
key, err := x509.ParsePKCS8PrivateKey(encryptedKey)
|
||||
if err != nil {
|
||||
return nil, errors.New("pkcs8: incorrect password")
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
|
||||
func convertPrivateKeyToPKCS8(priv interface{}) ([]byte, error) {
|
||||
var pkey privateKeyInfo
|
||||
|
||||
switch priv := priv.(type) {
|
||||
case *ecdsa.PrivateKey:
|
||||
eckey, err := x509.MarshalECPrivateKey(priv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
oidNamedCurve, ok := oidFromNamedCurve(priv.Curve)
|
||||
if !ok {
|
||||
return nil, errors.New("pkcs8: unknown elliptic curve")
|
||||
}
|
||||
|
||||
// Per RFC5958, if publicKey is present, then version is set to v2(1) else version is set to v1(0).
|
||||
// But openssl set to v1 even publicKey is present
|
||||
pkey.Version = 1
|
||||
pkey.PrivateKeyAlgorithm = make([]asn1.ObjectIdentifier, 2)
|
||||
pkey.PrivateKeyAlgorithm[0] = oidPublicKeyECDSA
|
||||
pkey.PrivateKeyAlgorithm[1] = oidNamedCurve
|
||||
pkey.PrivateKey = eckey
|
||||
case *rsa.PrivateKey:
|
||||
|
||||
// Per RFC5958, if publicKey is present, then version is set to v2(1) else version is set to v1(0).
|
||||
// But openssl set to v1 even publicKey is present
|
||||
pkey.Version = 0
|
||||
pkey.PrivateKeyAlgorithm = make([]asn1.ObjectIdentifier, 1)
|
||||
pkey.PrivateKeyAlgorithm[0] = oidPublicKeyRSA
|
||||
pkey.PrivateKey = x509.MarshalPKCS1PrivateKey(priv)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported key type: %T", priv)
|
||||
}
|
||||
|
||||
return asn1.Marshal(pkey)
|
||||
}
|
||||
|
||||
func convertPrivateKeyToPKCS8Encrypted(priv interface{}, password []byte) ([]byte, error) {
|
||||
// Convert private key into PKCS8 format
|
||||
pkey, err := convertPrivateKeyToPKCS8(priv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Calculate key from password based on PKCS5 algorithm
|
||||
// Use 8 byte salt, 16 byte IV, and 2048 iteration
|
||||
iter := 2048
|
||||
salt := make([]byte, 8)
|
||||
iv := make([]byte, 16)
|
||||
_, err = rand.Read(salt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = rand.Read(iv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
key := pbkdf2.Key(password, salt, iter, 32, sha256.New)
|
||||
|
||||
// Use AES256-CBC mode, pad plaintext with PKCS5 padding scheme
|
||||
padding := aes.BlockSize - len(pkey)%aes.BlockSize
|
||||
if padding > 0 {
|
||||
n := len(pkey)
|
||||
pkey = append(pkey, make([]byte, padding)...)
|
||||
for i := 0; i < padding; i++ {
|
||||
pkey[n+i] = byte(padding)
|
||||
}
|
||||
}
|
||||
|
||||
encryptedKey := make([]byte, len(pkey))
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mode := cipher.NewCBCEncrypter(block, iv)
|
||||
mode.CryptBlocks(encryptedKey, pkey)
|
||||
|
||||
// pbkdf2algo := pbkdf2Algorithms{oidPKCS5PBKDF2, pbkdf2Params{salt, iter, prfParam{oidHMACWithSHA256}}}
|
||||
|
||||
pbkdf2algo := pbkdf2Algorithms{oidPKCS5PBKDF2, pbkdf2Params{salt, iter, prfParam{oidHMACWithSHA256, asn1.RawValue{Tag: asn1.TagNull}}}}
|
||||
pbkdf2encs := pbkdf2Encs{oidAES256CBC, iv}
|
||||
pbes2algo := pbes2Algorithms{oidPBES2, pbes2Params{pbkdf2algo, pbkdf2encs}}
|
||||
|
||||
encryptedPkey := encryptedPrivateKeyInfo{pbes2algo, encryptedKey}
|
||||
|
||||
return asn1.Marshal(encryptedPkey)
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if v == nil {
|
||||
return convertPrivateKeyToPKCS8(priv)
|
||||
}
|
||||
|
||||
password := v[0]
|
||||
return convertPrivateKeyToPKCS8Encrypted(priv, password)
|
||||
}
|
6
vendor/modules.txt
vendored
6
vendor/modules.txt
vendored
|
@ -172,6 +172,8 @@ github.com/stretchr/testify/require
|
|||
github.com/t3rm1n4l/go-mega
|
||||
# github.com/xanzy/ssh-agent v0.2.1
|
||||
github.com/xanzy/ssh-agent
|
||||
# github.com/youmark/pkcs8 v0.0.0-20181201043747-70daafe5d78a
|
||||
github.com/youmark/pkcs8
|
||||
# github.com/yunify/qingstor-sdk-go/v3 v3.0.2
|
||||
github.com/yunify/qingstor-sdk-go/v3/config
|
||||
github.com/yunify/qingstor-sdk-go/v3/request/errors
|
||||
|
@ -207,10 +209,10 @@ golang.org/x/crypto/scrypt
|
|||
golang.org/x/crypto/ssh
|
||||
golang.org/x/crypto/ssh/terminal
|
||||
golang.org/x/crypto/bcrypt
|
||||
golang.org/x/crypto/pbkdf2
|
||||
golang.org/x/crypto/internal/subtle
|
||||
golang.org/x/crypto/poly1305
|
||||
golang.org/x/crypto/salsa20/salsa
|
||||
golang.org/x/crypto/pbkdf2
|
||||
golang.org/x/crypto/ssh/agent
|
||||
golang.org/x/crypto/curve25519
|
||||
golang.org/x/crypto/ed25519
|
||||
|
@ -239,9 +241,9 @@ golang.org/x/net/trace
|
|||
golang.org/x/net/internal/timeseries
|
||||
# golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
|
||||
golang.org/x/oauth2
|
||||
golang.org/x/oauth2/jws
|
||||
golang.org/x/oauth2/google
|
||||
golang.org/x/oauth2/internal
|
||||
golang.org/x/oauth2/jws
|
||||
golang.org/x/oauth2/jwt
|
||||
# golang.org/x/sync v0.0.0-20190423024810-112230192c58
|
||||
golang.org/x/sync/errgroup
|
||||
|
|
Loading…
Reference in New Issue
Block a user