func XMLSecDSigCtxSignDocument(ctx PtrSource, doc types.Document) error { ctxptr, err := validDSigCtxPtr(ctx) if err != nil { return err } root, err := doc.DocumentElement() if err != nil { return err } rootptr, err := validNodePtr(root) if err != nil { return err } cname := stringToXMLChar(SignatureNode) cns := stringToXMLChar(DSigNs) defer C.free(unsafe.Pointer(cname)) defer C.free(unsafe.Pointer(cns)) nodeptr := C.xmlSecFindNode(rootptr, cname, cns) if nodeptr == nil { return errors.New("failed to find start node") } return xmlSecDSigCtxSignRaw(ctxptr, nodeptr) }
func findSignatureNode(n *C.xmlNode) *C.xmlNode { /* move this out to C so we can just static/const it? */ cname := stringToXMLChar(SignatureNode) cns := stringToXMLChar(DSigNs) defer C.free(unsafe.Pointer(cname)) defer C.free(unsafe.Pointer(cns)) return C.xmlSecFindNode(n, cname, cns) }
// 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 }
// Sign returns a version of doc signed with key according to // the XMLDSIG standard. doc is a template document meaning // that it contains an `http://www.w3.org/2000/09/xmldsig#Signature` // element whose properties define how and what to sign. func Sign(key []byte, doc []byte, opts SignatureOptions) ([]byte, error) { startProcessingXML() defer stopProcessingXML() ctx := C.xmlSecDSigCtxCreate(nil) if ctx == nil { return nil, errors.New("failed to create signature context") } defer C.xmlSecDSigCtxDestroy(ctx) ctx.signKey = C.xmlSecCryptoAppKeyLoadMemory( (*C.xmlSecByte)(unsafe.Pointer(&key[0])), C.xmlSecSize(len(key)), C.xmlSecKeyDataFormatPem, nil, nil, nil) if ctx.signKey == nil { return nil, errors.New("failed to load pem key") } parsedDoc, err := newDoc(doc, opts.XMLID) if err != nil { return nil, err } defer closeDoc(parsedDoc) node := C.xmlSecFindNode(C.xmlDocGetRootElement(parsedDoc), (*C.xmlChar)(unsafe.Pointer(&C.xmlSecNodeSignature)), (*C.xmlChar)(unsafe.Pointer(&C.xmlSecDSigNs))) if node == nil { return nil, errors.New("cannot find start node") } if rv := C.xmlSecDSigCtxSign(ctx, node); rv < 0 { return nil, errors.New("failed to sign") } return dumpDoc(parsedDoc), nil }
// Verify checks that the signature in doc is valid according // to the XMLDSIG specification. publicKey is the public part of // the key used to sign doc. If the signature is not correct, // this function returns ErrVerificationFailed. func Verify(publicKey []byte, doc []byte, opts SignatureOptions) error { startProcessingXML() defer stopProcessingXML() keysMngr := C.xmlSecKeysMngrCreate() if keysMngr == nil { return mustPopError() } defer C.xmlSecKeysMngrDestroy(keysMngr) if rv := C.xmlSecCryptoAppDefaultKeysMngrInit(keysMngr); rv < 0 { return mustPopError() } key := C.xmlSecCryptoAppKeyLoadMemory( (*C.xmlSecByte)(unsafe.Pointer(&publicKey[0])), C.xmlSecSize(len(publicKey)), C.xmlSecKeyDataFormatCertPem, nil, nil, nil) if key == nil { return mustPopError() } if rv := C.xmlSecCryptoAppKeyCertLoadMemory(key, (*C.xmlSecByte)(unsafe.Pointer(&publicKey[0])), C.xmlSecSize(len(publicKey)), C.xmlSecKeyDataFormatCertPem); rv < 0 { C.xmlSecKeyDestroy(key) return mustPopError() } if rv := C.xmlSecCryptoAppDefaultKeysMngrAdoptKey(keysMngr, key); rv < 0 { return mustPopError() } dsigCtx := C.xmlSecDSigCtxCreate(keysMngr) if dsigCtx == nil { return mustPopError() } defer C.xmlSecDSigCtxDestroy(dsigCtx) parsedDoc, err := newDoc(doc, opts.XMLID) if err != nil { return err } defer closeDoc(parsedDoc) node := C.xmlSecFindNode(C.xmlDocGetRootElement(parsedDoc), (*C.xmlChar)(unsafe.Pointer(&C.xmlSecNodeSignature)), (*C.xmlChar)(unsafe.Pointer(&C.xmlSecDSigNs))) if node == nil { return errors.New("cannot find start node") } if rv := C.xmlSecDSigCtxVerify(dsigCtx, node); rv < 0 { return ErrVerificationFailed } if dsigCtx.status != xmlSecDSigStatusSucceeded { return ErrVerificationFailed } return nil }