clean up, add documentation, fix lint errors

This commit is contained in:
Ross Kinder
2015-12-23 14:09:41 -05:00
parent 9cc70cf455
commit b31c1472a0
15 changed files with 191 additions and 130 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
coverage.html
coverage.out

View File

@@ -8,3 +8,8 @@ addons:
go: go:
- 1.5 - 1.5
script:
- golint *.go
- go vet ./...
- go test -v ./...

View File

@@ -19,7 +19,9 @@ import "C"
// #include <libxml/xmlmemory.h> // #include <libxml/xmlmemory.h>
import "C" import "C"
func DecryptXML(privateKey []byte, doc []byte) ([]byte, error) { // 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() startProcessingXML()
defer stopProcessingXML() defer stopProcessingXML()

File diff suppressed because one or more lines are too long

View File

@@ -21,44 +21,87 @@ package xmlsec
import "C" import "C"
import ( import (
"fmt" "errors"
"unsafe" "unsafe"
) )
// SessionCipherType represents which session cipher to use to encrypt the document.
type SessionCipherType int
const ( const (
DefaultAlgorithm = iota // DefaultSessionCipher (the zero value) represents the default session cipher, AES256-CBC
DefaultSessionCipher SessionCipherType = iota
// Aes128Cbc means the session cipher should be AES-128 in CBC mode.
Aes128Cbc Aes128Cbc
// Aes192Cbc means the session cipher should be AES-192 in CBC mode.
Aes192Cbc Aes192Cbc
// Aes256Cbc means the session cipher should be AES-256 in CBC mode.
Aes256Cbc Aes256Cbc
// Des3Cbc means the session cipher should be triple DES in CBC mode.
Des3Cbc Des3Cbc
DsaSha1 )
Sha1
Sha256 // CipherType represent which cipher to use to encrypt the document
Sha384 type CipherType int
Sha512
const (
// DefaultCipher (the zero value) represents the default cipher, RSA-OAEP
DefaultCipher CipherType = iota
// RsaOaep means the cipher should be RSA-OAEP
RsaOaep RsaOaep
// RsaPkcs1 means the cipher should be RSA-PKCS1
RsaPkcs1 RsaPkcs1
) )
type Options struct { // DigestAlgorithmType represent which digest algorithm to use when encrypting the document.
SessionCipher int type DigestAlgorithmType int
Cipher int
DigestAlgorithm int const (
// DefaultDigestAlgorithm (the zero value) represents the default cipher, SHA1
DefaultDigestAlgorithm DigestAlgorithmType = iota
// Sha1 means the digest algorithm should be SHA-1
Sha1
// Sha256 means the digest algorithm should be SHA-256
Sha256
// Sha384 means the digest algorithm should be SHA-384
Sha384
// Sha512 means the digest algorithm should be SHA-512
Sha512
)
// EncryptOptions specifies the ciphers to use to encrypt the document.
type EncryptOptions struct {
SessionCipher SessionCipherType
Cipher CipherType
DigestAlgorithm DigestAlgorithmType
} }
// XmlEncrypt encrypts the XML document to publicKey. var errInvalidAlgorithm = errors.New("invalid algorithm")
func XmlEncrypt(publicKey, doc []byte, opts Options) ([]byte, error) {
// Encrypt encrypts the XML document to publicKey and returns the encrypted
// document.
func Encrypt(publicKey, doc []byte, opts EncryptOptions) ([]byte, error) {
startProcessingXML() startProcessingXML()
defer stopProcessingXML() defer stopProcessingXML()
keysMngr := C.xmlSecKeysMngrCreate() keysMngr := C.xmlSecKeysMngrCreate()
if keysMngr == nil { if keysMngr == nil {
return nil, fmt.Errorf("xmlSecKeysMngrCreate failed") return nil, mustPopError()
} }
defer C.xmlSecKeysMngrDestroy(keysMngr) defer C.xmlSecKeysMngrDestroy(keysMngr)
if rv := C.xmlSecCryptoAppDefaultKeysMngrInit(keysMngr); rv < 0 { if rv := C.xmlSecCryptoAppDefaultKeysMngrInit(keysMngr); rv < 0 {
return nil, fmt.Errorf("xmlSecCryptoAppDefaultKeysMngrInit failed") return nil, mustPopError()
} }
key := C.xmlSecCryptoAppKeyLoadMemory( key := C.xmlSecCryptoAppKeyLoadMemory(
@@ -67,7 +110,7 @@ func XmlEncrypt(publicKey, doc []byte, opts Options) ([]byte, error) {
C.xmlSecKeyDataFormatCertPem, C.xmlSecKeyDataFormatCertPem,
nil, nil, nil) nil, nil, nil)
if key == nil { if key == nil {
return nil, fmt.Errorf("xmlSecCryptoAppKeyLoadMemory failed") return nil, mustPopError()
} }
if rv := C.xmlSecCryptoAppKeyCertLoadMemory(key, if rv := C.xmlSecCryptoAppKeyCertLoadMemory(key,
@@ -75,11 +118,11 @@ func XmlEncrypt(publicKey, doc []byte, opts Options) ([]byte, error) {
C.xmlSecSize(len(publicKey)), C.xmlSecSize(len(publicKey)),
C.xmlSecKeyDataFormatCertPem); rv < 0 { C.xmlSecKeyDataFormatCertPem); rv < 0 {
C.xmlSecKeyDestroy(key) C.xmlSecKeyDestroy(key)
return nil, fmt.Errorf("xmlSecCryptoAppKeyCertLoad failed") return nil, mustPopError()
} }
if rv := C.xmlSecCryptoAppDefaultKeysMngrAdoptKey(keysMngr, key); rv < 0 { if rv := C.xmlSecCryptoAppDefaultKeysMngrAdoptKey(keysMngr, key); rv < 0 {
return nil, fmt.Errorf("xmlSecCryptoAppDefaultKeysMngrAdoptKey failed") return nil, mustPopError()
} }
parsedDoc, err := newDoc(doc) parsedDoc, err := newDoc(doc)
@@ -90,7 +133,7 @@ func XmlEncrypt(publicKey, doc []byte, opts Options) ([]byte, error) {
var sessionCipherTransform C.xmlSecTransformId var sessionCipherTransform C.xmlSecTransformId
switch opts.SessionCipher { switch opts.SessionCipher {
case DefaultAlgorithm: case DefaultSessionCipher:
sessionCipherTransform = C.MY_xmlSecTransformAes256CbcId() sessionCipherTransform = C.MY_xmlSecTransformAes256CbcId()
case Aes256Cbc: case Aes256Cbc:
sessionCipherTransform = C.MY_xmlSecTransformAes256CbcId() sessionCipherTransform = C.MY_xmlSecTransformAes256CbcId()
@@ -101,7 +144,7 @@ func XmlEncrypt(publicKey, doc []byte, opts Options) ([]byte, error) {
case Des3Cbc: case Des3Cbc:
sessionCipherTransform = C.MY_xmlSecTransformDes3CbcId() sessionCipherTransform = C.MY_xmlSecTransformDes3CbcId()
default: default:
return nil, fmt.Errorf("XXX") return nil, errInvalidAlgorithm
} }
// create encryption template to encrypt XML file and replace // create encryption template to encrypt XML file and replace
@@ -109,7 +152,7 @@ func XmlEncrypt(publicKey, doc []byte, opts Options) ([]byte, error) {
encDataNode := C.xmlSecTmplEncDataCreate(parsedDoc, sessionCipherTransform, encDataNode := C.xmlSecTmplEncDataCreate(parsedDoc, sessionCipherTransform,
nil, (*C.xmlChar)(unsafe.Pointer(&C.xmlSecTypeEncElement)), nil, nil) nil, (*C.xmlChar)(unsafe.Pointer(&C.xmlSecTypeEncElement)), nil, nil)
if encDataNode == nil { if encDataNode == nil {
return nil, fmt.Errorf("xmlSecTmplEncDataCreate failed") return nil, mustPopError()
} }
defer func() { defer func() {
if encDataNode != nil { if encDataNode != nil {
@@ -120,19 +163,19 @@ func XmlEncrypt(publicKey, doc []byte, opts Options) ([]byte, error) {
// we want to put encrypted data in the <enc:CipherValue/> node // we want to put encrypted data in the <enc:CipherValue/> node
if C.xmlSecTmplEncDataEnsureCipherValue(encDataNode) == nil { if C.xmlSecTmplEncDataEnsureCipherValue(encDataNode) == nil {
return nil, fmt.Errorf("xmlSecTmplEncDataEnsureCipherValue failed") return nil, mustPopError()
} }
// add <dsig:KeyInfo/> // add <dsig:KeyInfo/>
keyInfoNode := C.xmlSecTmplEncDataEnsureKeyInfo(encDataNode, nil) keyInfoNode := C.xmlSecTmplEncDataEnsureKeyInfo(encDataNode, nil)
if keyInfoNode == nil { if keyInfoNode == nil {
return nil, fmt.Errorf("xmlSecTmplEncDataEnsureKeyInfo failed") return nil, mustPopError()
} }
// add <enc:EncryptedKey/> to store the encrypted session key // add <enc:EncryptedKey/> to store the encrypted session key
var cipherTransform C.xmlSecTransformId var cipherTransform C.xmlSecTransformId
switch opts.Cipher { switch opts.Cipher {
case DefaultAlgorithm: case DefaultCipher:
cipherTransform = C.MY_xmlSecTransformRsaOaepId() cipherTransform = C.MY_xmlSecTransformRsaOaepId()
case RsaOaep: case RsaOaep:
cipherTransform = C.MY_xmlSecTransformRsaOaepId() cipherTransform = C.MY_xmlSecTransformRsaOaepId()
@@ -141,39 +184,39 @@ func XmlEncrypt(publicKey, doc []byte, opts Options) ([]byte, error) {
} }
encKeyNode := C.xmlSecTmplKeyInfoAddEncryptedKey(keyInfoNode, cipherTransform, nil, nil, nil) encKeyNode := C.xmlSecTmplKeyInfoAddEncryptedKey(keyInfoNode, cipherTransform, nil, nil, nil)
if encKeyNode == nil { if encKeyNode == nil {
return nil, fmt.Errorf("xmlSecTmplKeyInfoAddEncryptedKey failed") return nil, mustPopError()
} }
// we want to put encrypted key in the <enc:CipherValue/> node // we want to put encrypted key in the <enc:CipherValue/> node
if C.xmlSecTmplEncDataEnsureCipherValue(encKeyNode) == nil { if C.xmlSecTmplEncDataEnsureCipherValue(encKeyNode) == nil {
return nil, fmt.Errorf("xmlSecTmplEncDataEnsureCipherValue failed") return nil, mustPopError()
} }
// add <dsig:KeyInfo/> and <dsig:KeyName/> nodes to <enc:EncryptedKey/> // add <dsig:KeyInfo/> and <dsig:KeyName/> nodes to <enc:EncryptedKey/>
keyInfoNode2 := C.xmlSecTmplEncDataEnsureKeyInfo(encKeyNode, nil) keyInfoNode2 := C.xmlSecTmplEncDataEnsureKeyInfo(encKeyNode, nil)
if keyInfoNode2 == nil { if keyInfoNode2 == nil {
return nil, fmt.Errorf("xmlSecTmplEncDataEnsureKeyInfo failed") return nil, mustPopError()
} }
// Add a DigestMethod element to the encryption method node // Add a DigestMethod element to the encryption method node
{ {
encKeyMethod := C.xmlSecTmplEncDataGetEncMethodNode(encKeyNode) encKeyMethod := C.xmlSecTmplEncDataGetEncMethodNode(encKeyNode)
var ns = constXmlChar("http://www.w3.org/2000/09/xmldsig#") var ns = constXMLChar("http://www.w3.org/2000/09/xmldsig#")
var strDigestMethod = constXmlChar("DigestMethod") var strDigestMethod = constXMLChar("DigestMethod")
var strAlgorithm = constXmlChar("Algorithm") var strAlgorithm = constXMLChar("Algorithm")
var algorithm *C.xmlChar var algorithm *C.xmlChar
switch opts.DigestAlgorithm { switch opts.DigestAlgorithm {
case Sha512: case Sha512:
algorithm = constXmlChar("http://www.w3.org/2001/04/xmlenc#sha512") algorithm = constXMLChar("http://www.w3.org/2001/04/xmlenc#sha512")
case Sha384: case Sha384:
algorithm = constXmlChar("http://www.w3.org/2001/04/xmldsig-more#sha384") algorithm = constXMLChar("http://www.w3.org/2001/04/xmldsig-more#sha384")
case Sha256: case Sha256:
algorithm = constXmlChar("http://www.w3.org/2001/04/xmlenc#sha256") algorithm = constXMLChar("http://www.w3.org/2001/04/xmlenc#sha256")
case Sha1: case Sha1:
algorithm = constXmlChar("http://www.w3.org/2000/09/xmldsig#sha1") algorithm = constXMLChar("http://www.w3.org/2000/09/xmldsig#sha1")
case DefaultAlgorithm: case DefaultDigestAlgorithm:
algorithm = constXmlChar("http://www.w3.org/2000/09/xmldsig#sha1") algorithm = constXMLChar("http://www.w3.org/2000/09/xmldsig#sha1")
default: default:
return nil, fmt.Errorf("unknown digest algorithm %d", opts.DigestAlgorithm) return nil, errInvalidAlgorithm
} }
node := C.xmlSecAddChild(encKeyMethod, strDigestMethod, ns) node := C.xmlSecAddChild(encKeyMethod, strDigestMethod, ns)
C.xmlSetProp(node, strAlgorithm, algorithm) C.xmlSetProp(node, strAlgorithm, algorithm)
@@ -182,22 +225,22 @@ func XmlEncrypt(publicKey, doc []byte, opts Options) ([]byte, error) {
// add our certificate to KeyInfoNode // add our certificate to KeyInfoNode
x509dataNode := C.xmlSecTmplKeyInfoAddX509Data(keyInfoNode2) x509dataNode := C.xmlSecTmplKeyInfoAddX509Data(keyInfoNode2)
if x509dataNode == nil { if x509dataNode == nil {
return nil, fmt.Errorf("xmlSecTmplKeyInfoAddX509Data failed") return nil, mustPopError()
} }
if dataNode := C.xmlSecTmplX509DataAddCertificate(x509dataNode); dataNode == nil { if dataNode := C.xmlSecTmplX509DataAddCertificate(x509dataNode); dataNode == nil {
return nil, fmt.Errorf("xmlSecTmplX509DataAddCertificate failed") return nil, mustPopError()
} }
// create encryption context // create encryption context
var encCtx = C.xmlSecEncCtxCreate(keysMngr) var encCtx = C.xmlSecEncCtxCreate(keysMngr)
if encCtx == nil { if encCtx == nil {
return nil, fmt.Errorf("xmlSecEncCtxCreate failed") return nil, mustPopError()
} }
defer C.xmlSecEncCtxDestroy(encCtx) defer C.xmlSecEncCtxDestroy(encCtx)
// generate a key of the appropriate type // generate a key of the appropriate type
switch opts.SessionCipher { switch opts.SessionCipher {
case DefaultAlgorithm: case DefaultSessionCipher:
encCtx.encKey = C.xmlSecKeyGenerate(C.MY_xmlSecKeyDataAesId(), 256, encCtx.encKey = C.xmlSecKeyGenerate(C.MY_xmlSecKeyDataAesId(), 256,
C.xmlSecKeyDataTypeSession) C.xmlSecKeyDataTypeSession)
case Aes128Cbc: case Aes128Cbc:
@@ -213,15 +256,15 @@ func XmlEncrypt(publicKey, doc []byte, opts Options) ([]byte, error) {
encCtx.encKey = C.xmlSecKeyGenerate(C.MY_xmlSecKeyDataDesId(), 192, encCtx.encKey = C.xmlSecKeyGenerate(C.MY_xmlSecKeyDataDesId(), 192,
C.xmlSecKeyDataTypeSession) C.xmlSecKeyDataTypeSession)
default: default:
return nil, fmt.Errorf("unknown cipher type %d", opts.SessionCipher) return nil, errInvalidAlgorithm
} }
if encCtx.encKey == nil { if encCtx.encKey == nil {
return nil, fmt.Errorf("xmlSecKeyGenerate failed") return nil, mustPopError()
} }
// encrypt the data // encrypt the data
if rv := C.xmlSecEncCtxXmlEncrypt(encCtx, encDataNode, C.xmlDocGetRootElement(parsedDoc)); rv < 0 { if rv := C.xmlSecEncCtxXmlEncrypt(encCtx, encDataNode, C.xmlDocGetRootElement(parsedDoc)); rv < 0 {
return nil, fmt.Errorf("xmlSecEncCtxXmlEncrypt failed") return nil, mustPopError()
} }
encDataNode = nil // the template is inserted in the doc, so we don't own it encDataNode = nil // the template is inserted in the doc, so we don't own it

File diff suppressed because one or more lines are too long

View File

@@ -82,10 +82,10 @@ cvCsEFiJZ4AbF+DgmO6TarJ8O05t8zvnOwJlNCASPZRH/JmF8tX0hoHuAQ==</ds:X509Certificate
} }
func (testSuite *EncryptTest) TestEncrypt(c *C) { func (testSuite *EncryptTest) TestEncrypt(c *C) {
encryptedString, err := XmlEncrypt(testSuite.Cert, testSuite.Plaintext, Options{}) encryptedString, err := Encrypt(testSuite.Cert, testSuite.Plaintext, EncryptOptions{})
c.Assert(err, IsNil) c.Assert(err, IsNil)
actualPlaintext, err := DecryptXML(testSuite.Key, encryptedString) actualPlaintext, err := Decrypt(testSuite.Key, encryptedString)
c.Assert(err, IsNil) c.Assert(err, IsNil)
plaintextDoc, _ := newDoc(testSuite.Plaintext) plaintextDoc, _ := newDoc(testSuite.Plaintext)

View File

@@ -10,7 +10,7 @@ import (
var globalErrors = map[uintptr]errset.ErrSet{} var globalErrors = map[uintptr]errset.ErrSet{}
type Error struct { type libraryError struct {
FileName string FileName string
Line int Line int
FuncName string FuncName string
@@ -20,7 +20,7 @@ type Error struct {
Message string Message string
} }
func (e Error) Error() string { func (e libraryError) Error() string {
return fmt.Sprintf( return fmt.Sprintf(
"func=%s:file=%s:line=%d:obj=%s:subj=%s:error=%d:%s", "func=%s:file=%s:line=%d:obj=%s:subj=%s:error=%d:%s",
e.FuncName, e.FuncName,
@@ -34,7 +34,7 @@ func (e Error) Error() string {
//export onError //export onError
func onError(file *C.char, line C.int, funcName *C.char, errorObject *C.char, errorSubject *C.char, reason C.int, msg *C.char) { func onError(file *C.char, line C.int, funcName *C.char, errorObject *C.char, errorSubject *C.char, reason C.int, msg *C.char) {
err := Error{ err := libraryError{
FuncName: C.GoString(funcName), FuncName: C.GoString(funcName),
FileName: C.GoString(file), FileName: C.GoString(file),
Line: int(line), Line: int(line),
@@ -42,7 +42,7 @@ func onError(file *C.char, line C.int, funcName *C.char, errorObject *C.char, er
Subject: C.GoString(errorSubject), Subject: C.GoString(errorSubject),
Reason: int(reason), Reason: int(reason),
Message: C.GoString(msg)} Message: C.GoString(msg)}
threadID := getThreadId() threadID := getThreadID()
globalErrors[threadID] = append(globalErrors[threadID], err) globalErrors[threadID] = append(globalErrors[threadID], err)
} }
@@ -51,21 +51,31 @@ func onError(file *C.char, line C.int, funcName *C.char, errorObject *C.char, er
// error object. // error object.
func startProcessingXML() { func startProcessingXML() {
runtime.LockOSThread() runtime.LockOSThread()
globalErrors[getThreadId()] = errset.ErrSet{} globalErrors[getThreadID()] = errset.ErrSet{}
} }
// stopProcessingXML unlocks the goroutine-thread lock and deletes the current // stopProcessingXML unlocks the goroutine-thread lock and deletes the current
// error stack. // error stack.
func stopProcessingXML() { func stopProcessingXML() {
runtime.UnlockOSThread() runtime.UnlockOSThread()
delete(globalErrors, getThreadId()) delete(globalErrors, getThreadID())
} }
// popError returns the global error for the current thread and resets it to // popError returns the global error for the current thread and resets it to
// an empty error. Returns nil if no errors have occurred. // an empty error. Returns nil if no errors have occurred.
func popError() error { func popError() error {
threadID := getThreadId() threadID := getThreadID()
rv := globalErrors[threadID].ReturnValue() rv := globalErrors[threadID].ReturnValue()
globalErrors[threadID] = errset.ErrSet{} globalErrors[threadID] = errset.ErrSet{}
return rv return rv
} }
// mustPopError is like popError except that if there is no error on the stack
// it returns a generic error.
func mustPopError() error {
err := popError()
if err == nil {
err = fmt.Errorf("libxmlsec: call failed")
}
return err
}

View File

@@ -33,7 +33,7 @@ func main() {
buf, err := ioutil.ReadAll(os.Stdin) buf, err := ioutil.ReadAll(os.Stdin)
if *doSign { if *doSign {
signedBuf, err := xmlsec.Sign(key, buf, xmlsec.DsigOptions{}) signedBuf, err := xmlsec.Sign(key, buf, xmlsec.SignatureOptions{})
if err != nil { if err != nil {
fmt.Printf("%s\n", err) fmt.Printf("%s\n", err)
os.Exit(1) os.Exit(1)
@@ -42,7 +42,7 @@ func main() {
} }
if *doVerify { if *doVerify {
err := xmlsec.Verify(key, buf, xmlsec.DsigOptions{}) err := xmlsec.Verify(key, buf, xmlsec.SignatureOptions{})
if err == xmlsec.ErrVerificationFailed { if err == xmlsec.ErrVerificationFailed {
fmt.Println("signature is not correct") fmt.Println("signature is not correct")
os.Exit(1) os.Exit(1)

View File

@@ -37,11 +37,12 @@ type Signature struct {
X509Certificate *SignatureX509Data `xml:"KeyInfo>X509Data,omitempty"` X509Certificate *SignatureX509Data `xml:"KeyInfo>X509Data,omitempty"`
} }
// SignatureX509Data represents the <X509Data> element of <Signature>
type SignatureX509Data struct { type SignatureX509Data struct {
X509Certificate string `xml:"X509Certificate,omitempty"` X509Certificate string `xml:"X509Certificate,omitempty"`
} }
// DefaultSignature populates a default Signature that uses c14n and SHA1. // DefaultSignature returns a Signature struct that uses the default c14n and SHA1 settings.
func DefaultSignature(pemEncodedPublicKey []byte) Signature { func DefaultSignature(pemEncodedPublicKey []byte) Signature {
// xmlsec wants the key to be base64-encoded but *not* wrapped with the // xmlsec wants the key to be base64-encoded but *not* wrapped with the
// PEM flags // PEM flags

View File

@@ -5,6 +5,6 @@ import "unsafe"
// #include <pthread.h> // #include <pthread.h>
import "C" import "C"
func getThreadId() uintptr { func getThreadID() uintptr {
return uintptr(unsafe.Pointer(C.pthread_self())) return uintptr(unsafe.Pointer(C.pthread_self()))
} }

View File

@@ -2,6 +2,6 @@ package xmlsec
import "syscall" import "syscall"
func getThreadId() uintptr { func getThreadID() uintptr {
return uintptr(syscall.Gettid()) return uintptr(syscall.Gettid())
} }

View File

@@ -2,7 +2,6 @@ package xmlsec
import ( import (
"errors" "errors"
"fmt"
"unsafe" "unsafe"
) )
@@ -15,9 +14,9 @@ import (
// #include <xmlsec/crypto.h> // #include <xmlsec/crypto.h>
import "C" import "C"
// DsigOptions represents additional, less commonly used, options for Sign and // SignatureOptions represents additional, less commonly used, options for Sign and
// Verify // Verify
type DsigOptions struct { type SignatureOptions struct {
// Specify the name of ID attributes for specific elements. This // Specify the name of ID attributes for specific elements. This
// may be required if the signed document contains Reference elements // may be required if the signed document contains Reference elements
// that define which parts of the document are to be signed. // that define which parts of the document are to be signed.
@@ -28,18 +27,19 @@ type DsigOptions struct {
XMLID []XMLIDOption XMLID []XMLIDOption
} }
// XMLIDOption represents the definition of an XML reference element
// (See http://www.w3.org/TR/xml-id/)
type XMLIDOption struct { type XMLIDOption struct {
ElementName string ElementName string
ElementNamespace string ElementNamespace string
AttributeName string AttributeName string
} }
// Sign returns a version of docStr signed with key according to // Sign returns a version of doc signed with key according to
// the XML-DSIG standard. docStr is a template document meaning // the XML-DSIG standard. doc is a template document meaning
// that it contains a `Signature` element in the // that it contains an `http://www.w3.org/2000/09/xmldsig#Signature`
// http://www.w3.org/2000/09/xmldsig# namespace. // element whose properties define how and what to sign.
func Sign(key []byte, doc []byte, opts DsigOptions) ([]byte, error) { func Sign(key []byte, doc []byte, opts SignatureOptions) ([]byte, error) {
startProcessingXML() startProcessingXML()
defer stopProcessingXML() defer stopProcessingXML()
@@ -88,22 +88,22 @@ const (
xmlSecDSigStatusInvalid = 2 xmlSecDSigStatusInvalid = 2
) )
// Verify checks that the signature in docStr is valid according // Verify checks that the signature in doc is valid according
// to the XML-DSIG specification. publicKey is the public part of // to the XML-DSIG specification. publicKey is the public part of
// the key used to sign docStr. If the signature is not correct, // the key used to sign doc. If the signature is not correct,
// this function returns ErrVerificationFailed. // this function returns ErrVerificationFailed.
func Verify(publicKey []byte, doc []byte, opts DsigOptions) error { func Verify(publicKey []byte, doc []byte, opts SignatureOptions) error {
startProcessingXML() startProcessingXML()
defer stopProcessingXML() defer stopProcessingXML()
keysMngr := C.xmlSecKeysMngrCreate() keysMngr := C.xmlSecKeysMngrCreate()
if keysMngr == nil { if keysMngr == nil {
return fmt.Errorf("xmlSecKeysMngrCreate failed") return mustPopError()
} }
defer C.xmlSecKeysMngrDestroy(keysMngr) defer C.xmlSecKeysMngrDestroy(keysMngr)
if rv := C.xmlSecCryptoAppDefaultKeysMngrInit(keysMngr); rv < 0 { if rv := C.xmlSecCryptoAppDefaultKeysMngrInit(keysMngr); rv < 0 {
return fmt.Errorf("xmlSecCryptoAppDefaultKeysMngrInit failed") return mustPopError()
} }
key := C.xmlSecCryptoAppKeyLoadMemory( key := C.xmlSecCryptoAppKeyLoadMemory(
@@ -112,7 +112,7 @@ func Verify(publicKey []byte, doc []byte, opts DsigOptions) error {
C.xmlSecKeyDataFormatCertPem, C.xmlSecKeyDataFormatCertPem,
nil, nil, nil) nil, nil, nil)
if key == nil { if key == nil {
return fmt.Errorf("xmlSecCryptoAppKeyLoadMemory failed") return mustPopError()
} }
if rv := C.xmlSecCryptoAppKeyCertLoadMemory(key, if rv := C.xmlSecCryptoAppKeyCertLoadMemory(key,
@@ -120,16 +120,16 @@ func Verify(publicKey []byte, doc []byte, opts DsigOptions) error {
C.xmlSecSize(len(publicKey)), C.xmlSecSize(len(publicKey)),
C.xmlSecKeyDataFormatCertPem); rv < 0 { C.xmlSecKeyDataFormatCertPem); rv < 0 {
C.xmlSecKeyDestroy(key) C.xmlSecKeyDestroy(key)
return fmt.Errorf("xmlSecCryptoAppKeyCertLoad failed") return mustPopError()
} }
if rv := C.xmlSecCryptoAppDefaultKeysMngrAdoptKey(keysMngr, key); rv < 0 { if rv := C.xmlSecCryptoAppDefaultKeysMngrAdoptKey(keysMngr, key); rv < 0 {
return fmt.Errorf("xmlSecCryptoAppDefaultKeysMngrAdoptKey failed") return mustPopError()
} }
dsigCtx := C.xmlSecDSigCtxCreate(keysMngr) dsigCtx := C.xmlSecDSigCtxCreate(keysMngr)
if dsigCtx == nil { if dsigCtx == nil {
return fmt.Errorf("xmlSecDSigCtxCreate failed") return mustPopError()
} }
defer C.xmlSecDSigCtxDestroy(dsigCtx) defer C.xmlSecDSigCtxDestroy(dsigCtx)

File diff suppressed because one or more lines are too long

View File

@@ -57,7 +57,6 @@ func newDoc(buf []byte) (*C.xmlDoc, error) {
} }
defer C.xmlFreeParserCtxt(ctx) defer C.xmlFreeParserCtxt(ctx)
//C.xmlCtxtUseOptions(ctx, C.int(p.Options))
C.xmlParseDocument(ctx) C.xmlParseDocument(ctx)
if ctx.wellFormed == C.int(0) { if ctx.wellFormed == C.int(0) {
@@ -72,7 +71,7 @@ func newDoc(buf []byte) (*C.xmlDoc, error) {
return doc, nil return doc, nil
} }
func newDoc2(buf []byte, opts DsigOptions) (*C.xmlDoc, error) { func newDoc2(buf []byte, opts SignatureOptions) (*C.xmlDoc, error) {
ctx := C.xmlCreateMemoryParserCtxt((*C.char)(unsafe.Pointer(&buf[0])), ctx := C.xmlCreateMemoryParserCtxt((*C.char)(unsafe.Pointer(&buf[0])),
C.int(len(buf))) C.int(len(buf)))
if ctx == nil { if ctx == nil {
@@ -80,7 +79,6 @@ func newDoc2(buf []byte, opts DsigOptions) (*C.xmlDoc, error) {
} }
defer C.xmlFreeParserCtxt(ctx) defer C.xmlFreeParserCtxt(ctx)
//C.xmlCtxtUseDsigOptions(ctx, C.int(p.DsigOptions))
C.xmlParseDocument(ctx) C.xmlParseDocument(ctx)
if ctx.wellFormed == C.int(0) { if ctx.wellFormed == C.int(0) {
@@ -146,6 +144,6 @@ func dumpDoc(doc *C.xmlDoc) []byte {
return []byte(rv) return []byte(rv)
} }
func constXmlChar(s string) *C.xmlChar { func constXMLChar(s string) *C.xmlChar {
return (*C.xmlChar)(unsafe.Pointer(C.CString(s))) return (*C.xmlChar)(unsafe.Pointer(C.CString(s)))
} }