Skip to content

Commit 4f86bad

Browse files
committed
rsa.go: add ImportRSAPublicKeyBlob and ImportRSAPrivateKeyBlob.
1 parent 4d91dcc commit 4f86bad

File tree

1 file changed

+111
-0
lines changed

1 file changed

+111
-0
lines changed

wincrypto/rsa.go

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"encoding/binary"
88
"encoding/pem"
99
"errors"
10+
"fmt"
1011
"math/big"
1112
)
1213

@@ -70,6 +71,116 @@ func ParseRSAPrivateKey(der []byte) (*rsa.PrivateKey, error) {
7071
}
7172
}
7273

74+
// ImportRSAPublicKeyBlob is used to import rsa public key with PublicKeyBlob.
75+
func ImportRSAPublicKeyBlob(data []byte) (*rsa.PublicKey, error) {
76+
reader := bytes.NewReader(data)
77+
var bh blobHeader
78+
err := binary.Read(reader, binary.LittleEndian, &bh)
79+
if err != nil {
80+
return nil, fmt.Errorf("failed to read blob header: %s", err)
81+
}
82+
if bh.Type != publicKeyBlob {
83+
return nil, errors.New("invalid blob type")
84+
}
85+
if bh.Version != curBlobVersion {
86+
return nil, errors.New("invalid blob version")
87+
}
88+
var rp rsaPubKey
89+
err = binary.Read(reader, binary.LittleEndian, &rp)
90+
if err != nil {
91+
return nil, fmt.Errorf("failed to read blob public key: %s", err)
92+
}
93+
if rp.Magic != magicRSA1 {
94+
return nil, errors.New("invalid blob magic")
95+
}
96+
if rp.BitLen%8 != 0 {
97+
return nil, errors.New("invalid blob bit length")
98+
}
99+
modulus := make([]byte, rp.BitLen/8)
100+
err = binary.Read(reader, binary.LittleEndian, modulus)
101+
if err != nil {
102+
return nil, fmt.Errorf("failed to read modulus: %s", err)
103+
}
104+
publicKey := rsa.PublicKey{
105+
N: big.NewInt(0).SetBytes(reverseBytes(modulus)),
106+
E: int(rp.PubExp),
107+
}
108+
return &publicKey, nil
109+
}
110+
111+
// ImportRSAPrivateKeyBlob is used to import rsa private key with PrivateKeyBlob.
112+
func ImportRSAPrivateKeyBlob(data []byte) (*rsa.PrivateKey, error) {
113+
reader := bytes.NewReader(data)
114+
var bh blobHeader
115+
err := binary.Read(reader, binary.LittleEndian, &bh)
116+
if err != nil {
117+
return nil, fmt.Errorf("failed to read blob header: %s", err)
118+
}
119+
if bh.Type != privateKeyBlob {
120+
return nil, errors.New("invalid blob type")
121+
}
122+
if bh.Version != curBlobVersion {
123+
return nil, errors.New("invalid blob version")
124+
}
125+
var rp rsaPubKey
126+
err = binary.Read(reader, binary.LittleEndian, &rp)
127+
if err != nil {
128+
return nil, fmt.Errorf("failed to read blob private key: %s", err)
129+
}
130+
if rp.Magic != magicRSA2 {
131+
return nil, errors.New("invalid blob magic")
132+
}
133+
if rp.BitLen%8 != 0 {
134+
return nil, errors.New("invalid blob bit length")
135+
}
136+
modulus := make([]byte, rp.BitLen/8)
137+
err = binary.Read(reader, binary.LittleEndian, modulus)
138+
if err != nil {
139+
return nil, fmt.Errorf("failed to read modulus: %s", err)
140+
}
141+
publicKey := rsa.PublicKey{
142+
N: big.NewInt(0).SetBytes(reverseBytes(modulus)),
143+
E: int(rp.PubExp),
144+
}
145+
// read primes
146+
p1b := make([]byte, rp.BitLen/16)
147+
err = binary.Read(reader, binary.LittleEndian, p1b)
148+
if err != nil {
149+
return nil, fmt.Errorf("failed to read prime1: %s", err)
150+
}
151+
p1 := big.NewInt(0).SetBytes(reverseBytes(p1b))
152+
p2b := make([]byte, rp.BitLen/16)
153+
err = binary.Read(reader, binary.LittleEndian, p2b)
154+
if err != nil {
155+
return nil, fmt.Errorf("failed to read prime2: %s", err)
156+
}
157+
p2 := big.NewInt(0).SetBytes(reverseBytes(p2b))
158+
// skip exponents and coefficient
159+
skipped := make([]byte, rp.BitLen/16*3)
160+
err = binary.Read(reader, binary.LittleEndian, skipped)
161+
if err != nil {
162+
return nil, fmt.Errorf("failed to read skipped fields: %s", err)
163+
}
164+
// read private exponent
165+
db := make([]byte, rp.BitLen/8)
166+
err = binary.Read(reader, binary.LittleEndian, db)
167+
if err != nil {
168+
return nil, fmt.Errorf("failed to read private exponent: %s", err)
169+
}
170+
d := big.NewInt(0).SetBytes(reverseBytes(db))
171+
privateKey := rsa.PrivateKey{
172+
PublicKey: publicKey,
173+
D: d,
174+
Primes: []*big.Int{p1, p2},
175+
}
176+
err = privateKey.Validate()
177+
if err != nil {
178+
return nil, fmt.Errorf("failed to validate private key: %s", err)
179+
}
180+
privateKey.Precompute()
181+
return &privateKey, nil
182+
}
183+
73184
// ExportRSAPublicKeyBlob is used to export rsa public key with PublicKeyBlob.
74185
func ExportRSAPublicKeyBlob(key *rsa.PublicKey, usage int) ([]byte, error) {
75186
var ku uint32

0 commit comments

Comments
 (0)