File: privkey.go

package info (click to toggle)
golang-github-aws-aws-sdk-go-v2 1.24.1-2~bpo12%2B1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-backports
  • size: 554,032 kB
  • sloc: java: 15,941; makefile: 419; sh: 175
file content (143 lines) | stat: -rw-r--r-- 3,683 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package sign

import (
	"crypto"
	"crypto/ecdsa"
	"crypto/ed25519"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io"
	"io/ioutil"
	"os"
)

// LoadPEMPrivKeyFile reads a PEM encoded RSA private key from the file name.
// A new RSA private key will be returned if no error.
func LoadPEMPrivKeyFile(name string) (key *rsa.PrivateKey, err error) {
	file, err := os.Open(name)
	if err != nil {
		return nil, err
	}

	defer func() {
		closeErr := file.Close()
		if err == nil {
			err = closeErr
		} else if closeErr != nil {
			err = fmt.Errorf("close error: %v, original error: %w", closeErr, err)
		}
	}()

	return LoadPEMPrivKey(file)
}

// LoadPEMPrivKey reads a PEM encoded RSA private key from the io.Reader.
// A new RSA private key will be returned if no error.
func LoadPEMPrivKey(reader io.Reader) (*rsa.PrivateKey, error) {
	block, err := loadPem(reader)
	if err != nil {
		return nil, err
	}

	return x509.ParsePKCS1PrivateKey(block.Bytes)
}

// LoadEncryptedPEMPrivKey decrypts the PEM encoded private key using the
// password provided returning a RSA private key. If the PEM data is invalid,
// or unable to decrypt an error will be returned.
//
// Deprecated: RFC 1423 PEM encryption is insecure. Callers using encrypted
// keys should instead decrypt that payload externally and pass it to
// [LoadPEMPrivKey].
func LoadEncryptedPEMPrivKey(reader io.Reader, password []byte) (*rsa.PrivateKey, error) {
	block, err := loadPem(reader)
	if err != nil {
		return nil, err
	}

	decryptedBlock, err := x509.DecryptPEMBlock(block, password)
	if err != nil {
		return nil, err
	}

	return x509.ParsePKCS1PrivateKey(decryptedBlock)
}

// LoadPEMPrivKeyPKCS8 reads a PEM-encoded RSA private key in PKCS8 format from
// the given reader.
//
// x509.ParsePKCS8PrivateKey can return multiple key types and this API does
// not discern between them. Callers in need of the underlying value must
// obtain it via type assertion:
//
//	key, err := LoadPEMPrivKeyPKCS8(r)
//	if err != nil { /* ... */ }
//
//	switch key.(type) {
//	case *rsa.PrivateKey:
//		// ...
//	case *ecdsa.PrivateKey:
//		// ...
//	case ed25519.PrivateKey:
//		// ...
//	default:
//		panic("unrecognized private key type")
//	}
//
// See aforementioned API docs for a full list of possible key types.
//
// If calling code can opaquely handle the returned key as a crypto.Signer, use
// [LoadPEMPrivKeyPKCS8AsSigner] instead.
func LoadPEMPrivKeyPKCS8(reader io.Reader) (interface{}, error) {
	block, err := loadPem(reader)
	if err != nil {
		return nil, fmt.Errorf("load pem: %v", err)
	}

	key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
	if err != nil {
		return nil, fmt.Errorf("parse pkcs8 key: %v", err)
	}

	return key, nil
}

var (
	_ crypto.Signer = (*rsa.PrivateKey)(nil)
	_ crypto.Signer = (*ecdsa.PrivateKey)(nil)
	_ crypto.Signer = (ed25519.PrivateKey)(nil)
)

// LoadPEMPrivKeyPKCS8AsSigner wraps [LoadPEMPrivKeyPKCS8] to expect a crypto.Signer.
func LoadPEMPrivKeyPKCS8AsSigner(reader io.Reader) (crypto.Signer, error) {
	key, err := LoadPEMPrivKeyPKCS8(reader)
	if err != nil {
		return nil, fmt.Errorf("load key: %v", err)
	}

	signer, ok := key.(crypto.Signer)
	if !ok {
		return nil, fmt.Errorf("key of type %T is not a crypto.Signer", key)
	}

	return signer, nil
}

func loadPem(reader io.Reader) (*pem.Block, error) {
	b, err := ioutil.ReadAll(reader)
	if err != nil {
		return nil, err
	}

	block, _ := pem.Decode(b)
	if block == nil {
		// pem.Decode will set block to nil if there is no PEM data in the input
		// the second parameter will contain the provided bytes that failed
		// to be decoded.
		return nil, fmt.Errorf("no valid PEM data provided")
	}

	return block, nil
}