forked from lestrrat-go/xmlsec
-
Notifications
You must be signed in to change notification settings - Fork 1
/
dsig.go
171 lines (145 loc) · 3.91 KB
/
dsig.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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package dsig
import (
"errors"
"github.com/lestrrat-go/libxml2/types"
"github.com/lestrrat-go/xmlsec/clib"
"github.com/lestrrat-go/xmlsec/crypto"
)
// NewCtx creates a new XML Signature Context
func NewCtx(mngr *crypto.KeyManager) (*Ctx, error) {
var ptr uintptr
var err error
if mngr == nil {
ptr, err = clib.XMLSecDSigCtxCreate(nil)
} else {
ptr, err = clib.XMLSecDSigCtxCreate(mngr)
}
if err != nil {
return nil, err
}
return &Ctx{ptr: ptr}, nil
}
func (d Ctx) Pointer() uintptr {
return d.ptr
}
// Free releases the underlying C structure
func (d *Ctx) Free() error {
return clib.XMLSecDSigCtxDestroy(d)
}
func (d *Ctx) SetKey(key clib.PtrSource) error {
return clib.XMLSecDSigCtxSetKey(d, key)
}
// Sign signs the given document. It automatically searches
// for the "Signature" node with the namespace "http://www.w3.org/2000/09/xmldsig#".
func (d *Ctx) Sign(doc types.Document) error {
return clib.XMLSecDSigCtxSignDocument(d, doc)
}
// SignNode signs the given node.
func (d *Ctx) SignNode(n types.Node) error {
return clib.XMLSecDSigCtxSignNode(d, n)
}
// Verify verifies the signature in the given document. It automatically searches
// for the "Signature" node with the namespace "http://www.w3.org/2000/09/xmldsig#".
func (d *Ctx) Verify(doc types.Document) error {
return clib.XMLSecDSigCtxVerifyDocument(d, doc)
}
// VerifyNode verifies the signature in the given node
func (d *Ctx) VerifyNode(n types.Node) error {
return clib.XMLSecDSigCtxVerifyNode(d, n)
}
// NewSignature creates a Signature object.
func NewSignature(n types.Node, c14n, sig TransformID, id string) (*Signature, error) {
doc, err := n.OwnerDocument()
if err != nil {
return nil, err
}
signnode, err := clib.XMLSecTmplSignatureCreateNsPref(
doc,
clib.TransformID(c14n),
clib.TransformID(sig),
id,
clib.Prefix,
)
if err != nil {
return nil, err
}
n.AddChild(signnode)
return &Signature{
signmethod: sig,
signnode: signnode,
}, nil
}
// AddReference adds a Reference node to the appropriate location
func (s *Signature) AddReference(digestMethod TransformID, id, uri, nodeType string) error {
rn, err := clib.XMLSecTmplSignatureAddReference(
s.signnode,
clib.TransformID(digestMethod),
id,
uri,
nodeType,
)
if err != nil {
return err
}
s.refnode = rn
return nil
}
// AddTransform adds a Transform node to the appropriate location
func (s *Signature) AddTransform(transformID TransformID) error {
if s.refnode == nil {
return errors.New("missing reference node: did you call AddReference() first?")
}
if _, err := clib.XMLSecTmplReferenceAddTransform(s.refnode, clib.TransformID(transformID)); err != nil {
return err
}
return nil
}
// EnsureKeyInfo adds a KeyInfo node to the apprpriate location
func (s *Signature) EnsureKeyInfo(ids ...string) error {
if s.keyinfo != nil {
return nil
}
var id string
if len(ids) > 0 {
id = ids[0]
}
keyinfo, err := clib.XMLSecTmplSignatureEnsureKeyInfo(s.signnode, id)
if err != nil {
return err
}
s.keyinfo = keyinfo
return nil
}
// AddKeyValue adds KeyValue nodes to appropriate location. Before adding
// these nodes, EnsureKeyInfo is called to makes ure KeyInfo node is
// created and added.
func (s *Signature) AddKeyValue() error {
s.EnsureKeyInfo()
if _, err := clib.XMLSecTmplKeyInfoAddKeyValue(s.keyinfo); err != nil {
return err
}
return nil
}
// AddX509Data adds a X509Data node to the apprpriate location
func (s *Signature) AddX509Data() error {
s.EnsureKeyInfo()
if _, err := clib.XMLSecTmplKeyInfoAddX509Data(s.keyinfo); err != nil {
return err
}
return nil
}
// Sign populates the signature for the payload. The signature is generated
// using the specified key
func (s *Signature) Sign(key *crypto.Key) error {
km, err := crypto.NewKeyManager()
ctx, err := NewCtx(km)
if err != nil {
return err
}
defer ctx.Free()
defer km.Free()
if err := km.AdoptKey(key); err != nil {
return err
}
return ctx.SignNode(s.signnode)
}