-
Notifications
You must be signed in to change notification settings - Fork 24
/
key_rsa.go
95 lines (79 loc) · 1.96 KB
/
key_rsa.go
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
package ssh
import (
"fmt"
"errors"
"math/big"
"crypto"
"crypto/rsa"
"golang.org/x/crypto/ssh"
)
// rsa
type KeyRsa struct {}
// 包装
func (this KeyRsa) Marshal(key crypto.PrivateKey, comment string) (string, []byte, []byte, error) {
k, ok := key.(*rsa.PrivateKey)
if !ok {
return "", nil, nil, errors.New(fmt.Sprintf("unsupported key type %T", key))
}
keyType := ssh.KeyAlgoRSA
E := new(big.Int).SetInt64(int64(k.PublicKey.E))
pubKey := struct {
KeyType string
E *big.Int
N *big.Int
}{
keyType,
E,
k.PublicKey.N,
}
pubkey := ssh.Marshal(pubKey)
// Marshal private key.
prikey := struct {
N *big.Int
E *big.Int
D *big.Int
Iqmp *big.Int
P *big.Int
Q *big.Int
Comment string
}{
k.PublicKey.N, E,
k.D, k.Precomputed.Qinv, k.Primes[0], k.Primes[1],
comment,
}
rest := ssh.Marshal(prikey)
return keyType, pubkey, rest, nil
}
// 解析
func (this KeyRsa) Parse(rest []byte) (crypto.PrivateKey, string, error) {
// https://github.com/openssh/openssh-portable/blob/master/sshkey.c
key := struct {
N *big.Int
E *big.Int
D *big.Int
Iqmp *big.Int
P *big.Int
Q *big.Int
Comment string
Pad []byte `ssh:"rest"`
}{}
if err := ssh.Unmarshal(rest, &key); err != nil {
return nil, "", err
}
if err := checkOpenSSHKeyPadding(key.Pad); err != nil {
return nil, "", err
}
pk := &rsa.PrivateKey{
PublicKey: rsa.PublicKey{
N: key.N,
E: int(key.E.Int64()),
},
D: key.D,
Primes: []*big.Int{key.P, key.Q},
}
if err := pk.Validate(); err != nil {
return nil, "", err
}
pk.Precompute()
return pk, key.Comment, nil
}