forked from crewjam/go-xmlsec
-
Notifications
You must be signed in to change notification settings - Fork 0
/
decrypt.go
76 lines (63 loc) · 1.84 KB
/
decrypt.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
package xmlsec
import (
"fmt"
"unsafe"
)
// #include <xmlsec/xmlsec.h>
// #include <xmlsec/xmltree.h>
// #include <xmlsec/xmlenc.h>
// #include <xmlsec/templates.h>
// #include <xmlsec/crypto.h>
import "C"
// #include <libxml/parser.h>
// #include <libxml/parserInternals.h>
// #include <libxml/xmlmemory.h>
import "C"
// Decrypt finds the first encrypted part of doc, decrypts it using
// privateKey and returns the plaintext of the embedded document.
func Decrypt(privateKey []byte, doc []byte) ([]byte, error) {
startProcessingXML()
defer stopProcessingXML()
keysMngr := C.xmlSecKeysMngrCreate()
if keysMngr == nil {
return nil, popError()
}
defer C.xmlSecKeysMngrDestroy(keysMngr)
if rv := C.xmlSecCryptoAppDefaultKeysMngrInit(keysMngr); rv < 0 {
return nil, popError()
}
key := C.xmlSecCryptoAppKeyLoadMemory(
(*C.xmlSecByte)(unsafe.Pointer(&privateKey[0])),
C.xmlSecSize(len(privateKey)),
C.xmlSecKeyDataFormatPem,
nil, nil, nil)
if key == nil {
return nil, popError()
}
if rv := C.xmlSecCryptoAppDefaultKeysMngrAdoptKey(keysMngr, key); rv < 0 {
return nil, popError()
}
parsedDoc, err := newDoc(doc, nil)
if err != nil {
return nil, err
}
defer closeDoc(parsedDoc)
// create encryption context
encCtx := C.xmlSecEncCtxCreate(keysMngr)
if encCtx == nil {
return nil, popError()
}
defer C.xmlSecEncCtxDestroy(encCtx)
encDataNode := C.xmlSecFindNode(C.xmlDocGetRootElement(parsedDoc),
(*C.xmlChar)(unsafe.Pointer(&C.xmlSecNodeEncryptedData)),
(*C.xmlChar)(unsafe.Pointer(&C.xmlSecEncNs)))
if encDataNode == nil {
return nil, fmt.Errorf("xmlSecFindNode cannot find EncryptedData node")
}
// decrypt the data
if rv := C.xmlSecEncCtxDecrypt(encCtx, encDataNode); rv < 0 {
return nil, popError()
}
encDataNode = nil // the template is inserted in the doc, so we don't own it
return dumpDoc(parsedDoc), nil
}