forked from li0ard/cpfx_go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtypes.go
151 lines (130 loc) · 3.01 KB
/
types.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
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
144
145
146
147
148
149
150
151
package main
import (
"crypto/x509/pkix"
"encoding/asn1"
)
type keyBlob struct {
Version int
AlgorithmIdentifier asn1.RawValue
Blob []byte
}
type privateKey struct {
Version int `asn1:"default:0"`
Algorithm struct {
Value asn1.ObjectIdentifier
Parameters struct {
Curve asn1.ObjectIdentifier
Digest asn1.ObjectIdentifier
}
}
PrivateKey []byte
}
type exportKeyBlobOids struct {
Id asn1.ObjectIdentifier
Value struct {
Curve asn1.ObjectIdentifier
Digest asn1.ObjectIdentifier
}
}
type exportKeyBlob struct {
Value struct {
Ukm []byte
Cek struct {
Enc []byte
Mac []byte
}
Oids asn1.RawValue
}
}
type pfxPdu struct {
Version int
AuthSafe contentInfo
MacData macData `asn1:"optional"`
}
type contentInfo struct {
ContentType asn1.ObjectIdentifier
Content asn1.RawValue `asn1:"tag:0,explicit,optional"`
}
type macData struct {
Mac digestInfo
MacSalt []byte
Iterations int `asn1:"optional,default:1"`
}
// from PKCS#7:
type digestInfo struct {
Algorithm pkix.AlgorithmIdentifier
Digest []byte
}
type safeBag struct {
Id asn1.ObjectIdentifier
Value asn1.RawValue `asn1:"tag:0,explicit"`
Attributes []pkcs12Attribute `asn1:"set,optional"`
}
type pkcs12Attribute struct {
Id asn1.ObjectIdentifier
Value asn1.RawValue `asn1:"set"`
}
type pbeInfo struct {
Header struct {
Algorithm asn1.ObjectIdentifier
Parameters struct {
Salt []byte
Rounds int
}
}
EncryptedKey []byte
}
func unmarshal(in []byte, out interface{}) error {
trailing, err := asn1.Unmarshal(in, out)
if err != nil {
return err
}
if len(trailing) != 0 {
panic("pkcs12: trailing data found")
}
return nil
}
func getKeybags(bin []byte) (bags []safeBag, err error) {
var pfx pfxPdu
oidDataContentType := asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 7, 1})
oidEncryptedDataContentType := asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 7, 6})
asn1.Unmarshal(bin, &pfx)
if pfx.Version != 3 {
panic("can only decode v3 PFX PDU's")
}
if !pfx.AuthSafe.ContentType.Equal(oidDataContentType) {
panic("only password-protected PFX is implemented")
}
if err := unmarshal(pfx.AuthSafe.Content.Bytes, &pfx.AuthSafe.Content); err != nil {
panic(err)
}
if len(pfx.MacData.Mac.Algorithm.Algorithm) == 0 {
panic("pkcs12: no MAC in data")
}
var authenticatedSafe []contentInfo
if err := unmarshal(pfx.AuthSafe.Content.Bytes, &authenticatedSafe); err != nil {
panic(err)
}
if len(authenticatedSafe) != 2 {
panic("expected exactly two items in the authenticated safe")
}
for _, ci := range authenticatedSafe {
var data []byte
switch {
case ci.ContentType.Equal(oidDataContentType):
if err := unmarshal(ci.Content.Bytes, &data); err != nil {
panic(err)
}
case ci.ContentType.Equal(oidEncryptedDataContentType):
return
default:
return
}
var safeContents []safeBag
if err := unmarshal(data, &safeContents); err != nil {
panic(err)
}
bags = append(bags, safeContents...)
}
return bags, nil
}