update package

This commit is contained in:
2018-12-13 00:31:06 +01:00
23 changed files with 750 additions and 135 deletions

5
.gitignore vendored
View File

@@ -1,2 +1,3 @@
coverage.html
coverage.out
target
vendor
/Dockerfile

View File

@@ -1,5 +1,15 @@
language: go
sudo: false # silence warning
sudo: false
branches:
except:
- release
branches:
only:
- master
- develop
addons:
apt:
@@ -8,14 +18,26 @@ addons:
- libxmlsec1-dev
go:
- 1.6
- 1.7
- '1.11.1'
- tip
install:
- go get -t ./...
- go get github.com/golang/lint/golint
matrix:
allow_failures:
- go: tip
before_install:
- if [ -n "$GH_USER" ]; then git config --global github.user ${GH_USER}; fi;
- if [ -n "$GH_TOKEN" ]; then git config --global github.token ${GH_TOKEN}; fi;
- go get github.com/mattn/goveralls
before_script:
- make deps
script:
- golint *.go
- go vet ./...
- go test -v ./...
- make qa
after_failure:
- cat ./target/test/report.xml
after_success:
- if [ "$TRAVIS_GO_VERSION" = "1.11.1" ]; then $HOME/gopath/bin/goveralls -covermode=count -coverprofile=target/report/coverage.out -service=travis-ci; fi;

View File

@@ -2,13 +2,13 @@ FROM ubuntu
RUN apt-get update -yy && \
apt-get install -yy git make curl libxml2-dev libxmlsec1-dev liblzma-dev pkg-config
RUN curl -s https://storage.googleapis.com/golang/go1.7.linux-amd64.tar.gz | tar -C /usr/local -xzf -
RUN curl -s https://storage.googleapis.com/golang/go1.11.2.linux-amd64.tar.gz | tar -C /usr/local -xzf -
ENV GOPATH=/go
ENV PATH=$PATH:/usr/local/go/bin:/go/bin
RUN mkdir -p /go/bin
ADD . /go/src/github.com/crewjam/go-xmlsec
WORKDIR /go/src/github.com/crewjam/go-xmlsec
ADD . /go/src/git.deineagentur.com/DeineAgenturUG/go-xmlsec
WORKDIR /go/src/git.deineagentur.com/DeineAgenturUG/go-xmlsec
RUN go get github.com/crewjam/errset
RUN go build -o /bin/xmldsig ./examples/xmldsig.go

View File

@@ -1,8 +1,8 @@
FROM ubuntu:16.04
RUN apt-get update -yy && \
apt-get install -yy git make curl pkg-config
apt-get install -yy git make curl pkg-config
RUN curl -s https://storage.googleapis.com/golang/go1.7.linux-amd64.tar.gz | tar -C /usr/local -xzf -
RUN curl -s https://storage.googleapis.com/golang/go1.7.3.linux-amd64.tar.gz | tar -C /usr/local -xzf -
ENV GOPATH=/go
ENV PATH=$PATH:/usr/local/go/bin:/go/bin
RUN mkdir -p /go/bin
@@ -22,7 +22,7 @@ RUN curl -sL ftp://xmlsoft.org/libxml2/libxml2-2.9.4.tar.gz | tar -xzf - && \
--without-history \
--without-html \
--without-http \
--without-iconv \
--without-iconv \
--without-icu \
--without-iso8859x \
--without-legacy \
@@ -31,7 +31,7 @@ RUN curl -sL ftp://xmlsoft.org/libxml2/libxml2-2.9.4.tar.gz | tar -xzf - && \
--with-output \
--without-pattern \
--with-push \
--without-python \
--without-python \
--without-reader \
--without-readline \
--without-regexps \
@@ -53,8 +53,7 @@ RUN curl -sL ftp://xmlsoft.org/libxml2/libxml2-2.9.4.tar.gz | tar -xzf - && \
--without-coverage && \
make install
RUN \
curl -sL ftp://ftp.openssl.org/source/openssl-1.0.2j.tar.gz | tar -xzf - && \
RUN curl -sL ftp://ftp.openssl.org/source/openssl-1.0.2j.tar.gz | tar -xzf - && \
cd openssl-1.0.2j && \
./config \
no-shared \
@@ -70,28 +69,28 @@ RUN \
make depend install
RUN curl -sL http://www.aleksey.com/xmlsec/download/xmlsec1-1.2.22.tar.gz | tar -xzf - && \
cd xmlsec1-1.2.22 && \
./configure \
--enable-static \
--disable-shared \
--disable-crypto-dl \
--disable-apps-crypto-dl \
--enable-static-linking \
--without-gnu-ld \
--with-default-crypto=openssl \
--with-openssl=/usr/local/ssl \
--with-libxml=/usr/local \
--without-nss \
--without-nspr \
--without-gcrypt \
--without-gnutls \
--without-libxslt && \
make -C src install && \
make -C include install && \
make install-pkgconfigDATA
cd xmlsec1-1.2.22 && \
./configure \
--enable-static \
--disable-shared \
--disable-crypto-dl \
--disable-apps-crypto-dl \
--enable-static-linking \
--without-gnu-ld \
--with-default-crypto=openssl \
--with-openssl=/usr/local/ssl \
--with-libxml=/usr/local \
--without-nss \
--without-nspr \
--without-gcrypt \
--without-gnutls \
--without-libxslt && \
make -C src install && \
make -C include install && \
make install-pkgconfigDATA
ADD . /go/src/github.com/crewjam/go-xmlsec
WORKDIR /go/src/github.com/crewjam/go-xmlsec
ADD . /go/src/git.deineagentur.com/DeineAgenturUG/go-xmlsec
WORKDIR /go/src/git.deineagentur.com/DeineAgenturUG/go-xmlsec
RUN go get github.com/crewjam/errset
RUN go build -tags static -ldflags '-s -extldflags "-static"' -o /bin/xmldsig ./examples/xmldsig.go
RUN ldd /bin/xmldsig || true

177
Makefile Normal file
View File

@@ -0,0 +1,177 @@
# MAKEFILE
#
# @author Nicola Asuni <info@tecnick.com>
# @link https://git.deineagentur.com/DeineAgenturUG/go-xmlsec
# ------------------------------------------------------------------------------
# List special make targets that are not associated with files
.PHONY: help all test format fmtcheck vet lint coverage cyclo ineffassign misspell astscan qa deps clean nuke buildall dbuild
# Use bash as shell (Note: Ubuntu now uses dash which doesn't support PIPESTATUS).
SHELL=/bin/bash
# CVS path (path to the parent dir containing the project)
CVSPATH=git.deineagentur.com/DeineAgenturUG/go-xmlsec
# Project vendor
VENDOR=miracl
# Project name
PROJECT=go-xmlsec
# Project version
VERSION=$(shell cat VERSION)
# Project release number (packaging build number)
RELEASE=$(shell cat RELEASE)
# Current directory
CURRENTDIR=$(shell pwd)
# GO lang path
ifneq ($(GOPATH),)
ifeq ($(findstring $(GOPATH),$(CURRENTDIR)),)
# the defined GOPATH is not valid
GOPATH=
endif
endif
ifeq ($(GOPATH),)
# extract the GOPATH
GOPATH=$(firstword $(subst /src/, ,$(CURRENTDIR)))
endif
# Add the GO binary dir in the PATH
export PATH := $(GOPATH)/bin:$(PATH)
GOENV=GOPATH=$(GOPATH) CGO_CFLAGS_ALLOW='-w'
# --- MAKE TARGETS ---
# Display general help about this command
help:
@echo ""
@echo "$(PROJECT) Makefile."
@echo "GOPATH=$(GOPATH)"
@echo "The following commands are available:"
@echo ""
@echo " make qa : Run all the tests and static analysis reports"
@echo " make test : Run the unit tests"
@echo ""
@echo " make format : Format the source code"
@echo " make fmtcheck : Check if the source code has been formatted"
@echo " make vet : Check for suspicious constructs"
@echo " make lint : Check for style errors"
@echo " make coverage : Generate the coverage report"
@echo " make cyclo : Generate the cyclomatic complexity report"
@echo " make ineffassign : Detect ineffectual assignments"
@echo " make misspell : Detect commonly misspelled words in source files"
@echo " make astscan : GO AST scanner"
@echo ""
@echo " make docs : Generate source code documentation"
@echo ""
@echo " make deps : Get the dependencies"
@echo " make clean : Remove any build artifact"
@echo " make nuke : Deletes any intermediate file"
@echo ""
@echo " make buildall : Full build and test sequence"
@echo " make dbuild : Build everything inside a Docker container"
@echo ""
# Alias for help target
all: help
# Run the unit tests
test:
@mkdir -p target/test
$(GOENV) go test -covermode=atomic -bench=. -race -v . | \
tee >($(GOENV) go-junit-report > target/test/report.xml); \
test $${PIPESTATUS[0]} -eq 0
# Format the source code
format:
@find . -type f -name "*.go" -exec gofmt -s -w {} \;
# Check if the source code has been formatted
fmtcheck:
@mkdir -p target
@find . -type f -name "*.go" -exec gofmt -s -d {} \; | tee target/format.diff
@test ! -s target/format.diff || { echo "ERROR: the source code has not been formatted - please use 'make format' or 'gofmt'"; exit 1; }
# Check for syntax errors
vet:
$(GOENV) go vet .
# Check for style errors
lint:
$(GOENV) golint .
# Generate the coverage report
coverage:
@mkdir -p target/report
$(GOENV) go test -covermode=count -coverprofile=target/report/coverage.out -v . && \
$(GOENV) go tool cover -html=target/report/coverage.out -o target/report/coverage.html
# Report cyclomatic complexity
cyclo:
@mkdir -p target/report
$(GOENV) gocyclo -avg . | tee target/report/cyclo.txt ; test $${PIPESTATUS[0]} -eq 0
# Detect ineffectual assignments
ineffassign:
@mkdir -p target/report
$(GOENV) ineffassign . | tee target/report/ineffassign.txt ; test $${PIPESTATUS[0]} -eq 0
# Detect commonly misspelled words in source files
misspell:
@mkdir -p target/report
$(GOENV) misspell -error . | tee target/report/misspell.txt ; test $${PIPESTATUS[0]} -eq 0
# AST scanner
astscan:
@mkdir -p target/report
$(GOENV) gas ./*.go | tee target/report/astscan.txt ; test $${PIPESTATUS[0]} -eq 0 || true
# Generate source docs
docs:
@mkdir -p target/docs
nohup sh -c '$(GOENV) godoc -http=127.0.0.1:6060' > target/godoc_server.log 2>&1 &
wget --directory-prefix=target/docs/ --execute robots=off --retry-connrefused --recursive --no-parent --adjust-extension --page-requisites --convert-links http://127.0.0.1:6060/pkg/github.com/${VENDOR}/${PROJECT}/ ; kill -9 `lsof -ti :6060`
@echo '<html><head><meta http-equiv="refresh" content="0;./127.0.0.1:6060/pkg/'${CVSPATH}'/'${PROJECT}'/index.html"/></head><a href="./127.0.0.1:6060/pkg/'${CVSPATH}'/'${PROJECT}'/index.html">'${PKGNAME}' Documentation ...</a></html>' > target/docs/index.html
# Alias to run targets: fmtcheck test vet lint coverage
qa: fmtcheck test vet lint coverage cyclo ineffassign misspell astscan
# --- INSTALL ---
# Get the dependencies
deps:
GOPATH=$(GOPATH) go get $(go list ./... | grep -v /vendor/)
GOPATH=$(GOPATH) go get github.com/inconshreveable/mousetrap
GOPATH=$(GOPATH) go get golang.org/x/lint/golint
GOPATH=$(GOPATH) go get github.com/jstemmer/go-junit-report
GOPATH=$(GOPATH) go get github.com/axw/gocov/gocov
GOPATH=$(GOPATH) go get github.com/fzipp/gocyclo
GOPATH=$(GOPATH) go get github.com/gordonklaus/ineffassign
GOPATH=$(GOPATH) go get github.com/client9/misspell/cmd/misspell
GOPATH=$(GOPATH) go get github.com/securego/gosec/cmd/gosec/...
GOPATH=$(GOPATH) go get gopkg.in/check.v1
# Remove any build artifact
clean:
$(GOENV) go clean ./...
# Deletes any intermediate file
nuke:
rm -rf ./target
$(GOENV) go clean -i ./...
# Full build and test sequence
buildall: deps qa
# Build everything inside a Docker container
dbuild:
@mkdir -p target
@rm -rf target/*
@echo 0 > target/make.exit
CVSPATH=$(CVSPATH) VENDOR=$(VENDOR) PROJECT=$(PROJECT) MAKETARGET='$(MAKETARGET)' ./dockerbuild.sh
@exit `cat target/make.exit`

View File

@@ -1,6 +1,10 @@
# go-xmlsec
[![](https://godoc.org/github.com/crewjam/go-xmlsec?status.png)](http://godoc.org/github.com/crewjam/go-xmlsec) [![Build Status](https://travis-ci.org/crewjam/go-xmlsec.svg?branch=master)](https://travis-ci.org/crewjam/go-xmlsec)
[![Documentation](https://godoc.org/git.deineagentur.com/DeineAgenturUG/go-xmlsec?status.png)](http://godoc.org/git.deineagentur.com/DeineAgenturUG/go-xmlsec)
[![Master Build Status](https://secure.travis-ci.org/tecnickcom/go-xmlsec.png?branch=master)](https://travis-ci.org/tecnickcom/go-xmlsec?branch=master)
[![Master Coverage Status](https://coveralls.io/repos/tecnickcom/go-xmlsec/badge.svg?branch=master&service=github)](https://coveralls.io/github/tecnickcom/go-xmlsec?branch=master)
[![Go Report Card](https://goreportcard.com/badge/git.deineagentur.com/DeineAgenturUG/go-xmlsec)](https://goreportcard.com/report/git.deineagentur.com/DeineAgenturUG/go-xmlsec)
A partial wrapper for [xmlsec](https://www.aleksey.com/xmlsec).
@@ -43,12 +47,12 @@ As seems to be the case for many things in the XMLish world, the xmldsig and xml
This package uses cgo to wrap libxmlsec. As such, you'll need libxmlsec headers and a C compiler to make it work. On linux, this might look like:
$ apt-get install libxml2-dev libxmlsec1-dev pkg-config
$ go get github.com/crewjam/go-xmlsec
$ go get git.deineagentur.com/DeineAgenturUG/go-xmlsec
On Mac with homebrew, this might look like:
$ brew install libxmlsec1 libxml2 pkg-config
$ go get github.com/crewjam/go-xmlsec
$ go get git.deineagentur.com/DeineAgenturUG/go-xmlsec
# Static Linking

View File

@@ -1,18 +1,13 @@
// +build !static
package xmlsec
// #cgo pkg-config: xmlsec1 libxml-2.0
// #cgo linux CFLAGS: -w
// #cgo darwin CFLAGS: -Wno-invalid-pp-token -Wno-header-guard
// #cgo pkg-config: xmlsec1
// #cgo linux LDFLAGS: -lxml2 -lm
// #include <xmlsec/xmlsec.h>
// #include <xmlsec/xmltree.h>
// #include <xmlsec/xmlenc.h>
// #include <xmlsec/templates.h>
// #include <xmlsec/crypto.h>
import "C"
// #cgo pkg-config: libxml-2.0
// #include <libxml/parser.h>
// #include <libxml/parserInternals.h>
// #include <libxml/xmlmemory.h>

View File

@@ -1,19 +0,0 @@
// +build static
package xmlsec
// #cgo linux CFLAGS: -w
// #cgo darwin CFLAGS: -Wno-invalid-pp-token -Wno-header-guard
// #cgo pkg-config: --static xmlsec1
// #include <xmlsec/xmlsec.h>
// #include <xmlsec/xmltree.h>
// #include <xmlsec/xmlenc.h>
// #include <xmlsec/templates.h>
// #include <xmlsec/crypto.h>
import "C"
// #cgo pkg-config: --static libxml-2.0
// #include <libxml/parser.h>
// #include <libxml/parserInternals.h>
// #include <libxml/xmlmemory.h>
import "C"

View File

@@ -33,6 +33,7 @@ func Decrypt(privateKey []byte, doc []byte) ([]byte, error) {
return nil, popError()
}
// #nosec
key := C.xmlSecCryptoAppKeyLoadMemory(
(*C.xmlSecByte)(unsafe.Pointer(&privateKey[0])),
C.xmlSecSize(len(privateKey)),
@@ -59,6 +60,7 @@ func Decrypt(privateKey []byte, doc []byte) ([]byte, error) {
}
defer C.xmlSecEncCtxDestroy(encCtx)
// #nosec
encDataNode := C.xmlSecFindNode(C.xmlDocGetRootElement(parsedDoc),
(*C.xmlChar)(unsafe.Pointer(&C.xmlSecNodeEncryptedData)),
(*C.xmlChar)(unsafe.Pointer(&C.xmlSecEncNs)))
@@ -70,7 +72,6 @@ func Decrypt(privateKey []byte, doc []byte) ([]byte, error) {
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
}

58
dockerbuild.sh Executable file
View File

@@ -0,0 +1,58 @@
#!/bin/sh
#
# dockerbuild.sh
#
# Build the software inside a Docker container
#
# @author Nicola Asuni <info@tecnick.com>
# ------------------------------------------------------------------------------
# NOTES:
# This script requires Docker
# EXAMPLE USAGE:
# VENDOR=vendorname PROJECT=projectname MAKETARGET=buildall ./dockerbuild.sh
# Get vendor and project name
: ${CVSPATH:=project}
: ${VENDOR:=vendor}
: ${PROJECT:=project}
# make target to execute
: ${MAKETARGET:=buildall}
# Name of the base development Docker image
DOCKERDEV=${VENDOR}/dev_${PROJECT}
# Build the base environment and keep it cached locally
docker build -t ${DOCKERDEV} ./resources/DockerDev/
# Define the project root path
PRJPATH=/root/src/${CVSPATH}/${PROJECT}
# Generate a temporary Dockerfile to build and test the project
# NOTE: The exit status of the RUN command is stored to be returned later,
# so in case of error we can continue without interrupting this script.
cat > Dockerfile <<- EOM
FROM ${DOCKERDEV}
RUN mkdir -p ${PRJPATH}
ADD ./ ${PRJPATH}
WORKDIR ${PRJPATH}
RUN make ${MAKETARGET} || (echo \$? > target/make.exit)
EOM
# Define the temporary Docker image name
DOCKER_IMAGE_NAME=${VENDOR}/build_${PROJECT}
# Build the Docker image
docker build --no-cache -t ${DOCKER_IMAGE_NAME} .
# Start a container using the newly created Docker image
CONTAINER_ID=$(docker run -d ${DOCKER_IMAGE_NAME})
# Copy all build/test artifacts back to the host
docker cp ${CONTAINER_ID}:"${PRJPATH}/target" ./
# Remove the temporary container and image
docker rm -f ${CONTAINER_ID} || true
docker rmi -f ${DOCKER_IMAGE_NAME} || true

View File

@@ -91,6 +91,7 @@ var errInvalidAlgorithm = errors.New("invalid algorithm")
// Note: the invocations of C.CString() here return a pointer to a string
// allocated from the C heap that would normally need to freed by calling
// C.free, but because these are global, we can just leak them.
// #nosec
var (
constDsigNamespace = (*C.xmlChar)(unsafe.Pointer(C.CString("http://www.w3.org/2000/09/xmldsig#")))
constDigestMethod = (*C.xmlChar)(unsafe.Pointer(C.CString("DigestMethod")))
@@ -117,6 +118,7 @@ func Encrypt(publicKey, doc []byte, opts EncryptOptions) ([]byte, error) {
return nil, mustPopError()
}
// #nosec
key := C.xmlSecCryptoAppKeyLoadMemory(
(*C.xmlSecByte)(unsafe.Pointer(&publicKey[0])),
C.xmlSecSize(len(publicKey)),
@@ -126,6 +128,7 @@ func Encrypt(publicKey, doc []byte, opts EncryptOptions) ([]byte, error) {
return nil, mustPopError()
}
// #nosec
if rv := C.xmlSecCryptoAppKeyCertLoadMemory(key,
(*C.xmlSecByte)(unsafe.Pointer(&publicKey[0])),
C.xmlSecSize(len(publicKey)),
@@ -162,6 +165,7 @@ func Encrypt(publicKey, doc []byte, opts EncryptOptions) ([]byte, error) {
// create encryption template to encrypt XML file and replace
// its content with encryption result
// #nosec
encDataNode := C.xmlSecTmplEncDataCreate(parsedDoc, sessionCipherTransform,
nil, (*C.xmlChar)(unsafe.Pointer(&C.xmlSecTypeEncElement)), nil, nil)
if encDataNode == nil {
@@ -279,5 +283,8 @@ func Encrypt(publicKey, doc []byte, opts EncryptOptions) ([]byte, error) {
}
encDataNode = nil // the template is inserted in the doc, so we don't own it
return dumpDoc(parsedDoc), nil
rootNode := C.xmlDocGetRootElement(parsedDoc)
buf := dumpNode(rootNode)
return buf, nil
}

View File

@@ -49,8 +49,8 @@ func onXmlsecError(file *C.char, line C.int, funcName *C.char, errorObject *C.ch
globalErrors[threadID] = append(globalErrors[threadID], err)
}
//export onXmlError
func onXmlError(msg *C.char) {
//export onXMLError
func onXMLError(msg *C.char) {
threadID := getThreadID()
globalErrors[threadID] = append(globalErrors[threadID],
fmt.Errorf("%s", strings.TrimSuffix(C.GoString(msg), "\n")))

View File

@@ -8,7 +8,7 @@ package xmlsec
// #include <xmlsec/xmlsec.h>
// #include <xmlsec/errors.h>
//
// void onXmlError(const char *msg); // implemented in go
// void onXMLError(const char *msg); // implemented in go
// void onXmlsecError(const char *file, int line, const char *funcName, const char *errorObject, const char *errorSubject, int reason, const char *msg); // implemented in go
//
// static void onXmlGenericError_cgo(void *ctx, const char *format, ...) {
@@ -17,7 +17,7 @@ package xmlsec
// va_start(args, format);
// vsnprintf(buffer, 256, format, args);
// va_end (args);
// onXmlError(buffer);
// onXMLError(buffer);
// }
//
// static void onXmlsecError_cgo(const char *file, int line, const char *funcName, const char *errorObject, const char *errorSubject, int reason, const char *msg) {

View File

@@ -6,7 +6,7 @@ import (
"io/ioutil"
"os"
"github.com/gofly/go-xmlsec"
xmlsec "git.deineagentur.com/DeineAgenturUG/go-xmlsec"
)
func main() {
@@ -31,6 +31,10 @@ func main() {
}
buf, err := ioutil.ReadAll(os.Stdin)
if err != nil {
fmt.Printf("%s\n", err)
os.Exit(1)
}
if *doSign {
signedBuf, err := xmlsec.Sign(key, buf, xmlsec.SignatureOptions{})
@@ -38,7 +42,7 @@ func main() {
fmt.Printf("%s\n", err)
os.Exit(1)
}
os.Stdout.Write(signedBuf)
os.Stdout.Write(signedBuf) //#nosec
}
if *doVerify {

View File

@@ -0,0 +1,10 @@
# Dockerfile
#
# Linux development environment
#
# Extend the tecnickcom/alldev image defined in
# https://github.com/tecnickcom/alldev
# ------------------------------------------------------------------------------
FROM tecnickcom/alldev
MAINTAINER info@tecnick.com

24
resources/certs/cert1 Normal file
View File

@@ -0,0 +1,24 @@
-----BEGIN CERTIFICATE-----
MIIDzzCCAzigAwIBAgIJAK+ii7kzrdqtMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYD
VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3Vy
aXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEQMA4G
A1UECxMHUm9vdCBDQTEWMBQGA1UEAxMNQWxla3NleSBTYW5pbjEhMB8GCSqGSIb3
DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tMCAXDTE0MDUyMzE3NTIzOFoYDzIxMTQw
NDI5MTc1MjM4WjCBnDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWEx
PTA7BgNVBAoTNFhNTCBTZWN1cml0eSBMaWJyYXJ5IChodHRwOi8vd3d3LmFsZWtz
ZXkuY29tL3htbHNlYykxFjAUBgNVBAMTDUFsZWtzZXkgU2FuaW4xITAfBgkqhkiG
9w0BCQEWEnhtbHNlY0BhbGVrc2V5LmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgC
QQCyuvKJ2CuUPD33ghPt4Q8MilesHxVbbpyKfmabrYVpDGVDmOKKp337qJUZZ95K
fwlXbR2j0zyKWJmvRxUx+PsTAgMBAAGjggFFMIIBQTAMBgNVHRMEBTADAQH/MCwG
CWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNV
HQ4EFgQU/uTsUyTwlZXHELXhRLVdOWVa434wgeMGA1UdIwSB2zCB2IAUBrWkrKeq
dUTqFZxP3wWDT2oe/guhgbSkgbEwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpD
YWxpZm9ybmlhMT0wOwYDVQQKEzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDov
L3d3dy5hbGVrc2V5LmNvbS94bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYD
VQQDEw1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3Nl
eS5jb22CCQCvoou5M63arDANBgkqhkiG9w0BAQUFAAOBgQBuTAW63AgWqqUDPGi8
BiXbdKHhFP4J8qgkdv5WMa6SpSWVgNgOYXkK/BSg1aSmQtGv8/8UvBRPoJnO4y0N
jWUFf1ubOgUNmedYNLq7YbTp8yTGWeogCyM2xdWELMP8BMgQL0sP+MDAFMKO3itY
mEWnCEsP15HKSTms54RNj7oJ+A==
-----END CERTIFICATE-----

25
resources/certs/cert2 Normal file
View File

@@ -0,0 +1,25 @@
-----BEGIN CERTIFICATE-----
MIID9zCCA2CgAwIBAgIJAK+ii7kzrdqsMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYD
VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3Vy
aXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEQMA4G
A1UECxMHUm9vdCBDQTEWMBQGA1UEAxMNQWxla3NleSBTYW5pbjEhMB8GCSqGSIb3
DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tMCAXDTE0MDUyMzE3NTA1OVoYDzIxMTQw
NDI5MTc1MDU5WjCBrjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWEx
PTA7BgNVBAoTNFhNTCBTZWN1cml0eSBMaWJyYXJ5IChodHRwOi8vd3d3LmFsZWtz
ZXkuY29tL3htbHNlYykxEDAOBgNVBAsTB1Jvb3QgQ0ExFjAUBgNVBAMTDUFsZWtz
ZXkgU2FuaW4xITAfBgkqhkiG9w0BCQEWEnhtbHNlY0BhbGVrc2V5LmNvbTCBnzAN
BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtY4MCNj/qrOzVuex1BD/PuCYTDDOLLVj
tpKXQteQPqy0kgMwuQgRwdNnICIHQbnFKL40XoyACJVWKM7b0LkvWJNeyVzXPqEE
9ZPmNxWGUjVcr7powT7v8V7S2QflUnr8ZvR4XWwkZJ9EYKNhenijgJ5yYDrXCWdv
C+fnjBjv2LcCAwEAAaOCARcwggETMB0GA1UdDgQWBBQGtaSsp6p1ROoVnE/fBYNP
ah7+CzCB4wYDVR0jBIHbMIHYgBQGtaSsp6p1ROoVnE/fBYNPah7+C6GBtKSBsTCB
rjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhN
TCBTZWN1cml0eSBMaWJyYXJ5IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNl
YykxEDAOBgNVBAsTB1Jvb3QgQ0ExFjAUBgNVBAMTDUFsZWtzZXkgU2FuaW4xITAf
BgkqhkiG9w0BCQEWEnhtbHNlY0BhbGVrc2V5LmNvbYIJAK+ii7kzrdqsMAwGA1Ud
EwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEARpb86RP/ck55X+NunXeIX81i763b
j7Z1VJwFbA/QfupzxnqJ2IP/lxC8YxJ3Bp2IJMI7rC9r0poa41ZxI5rGHip97Dpg
sxPF9lkRUmKBBQjkICOq1w/4d2DRInBoqXttD+0WsqDfNDVK+7kSE07ytn3RzHCj
j0gv0PdxmuCsR/E=
-----END CERTIFICATE-----

23
resources/certs/cert3 Normal file
View File

@@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIIDpzCCA1GgAwIBAgIJAK+ii7kzrdqvMA0GCSqGSIb3DQEBBQUAMIGcMQswCQYD
VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3Vy
aXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEWMBQG
A1UEAxMNQWxla3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtz
ZXkuY29tMCAXDTE0MDUyMzE3NTUzNFoYDzIxMTQwNDI5MTc1NTM0WjCBxzELMAkG
A1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1
cml0eSBMaWJyYXJ5IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxKTAn
BgNVBAsTIFRlc3QgVGhpcmQgTGV2ZWwgUlNBIENlcnRpZmljYXRlMRYwFAYDVQQD
Ew1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5j
b20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEA09BtD3aeVt6DVDkk0dI7Vh7Ljqdn
sYmW0tbDVxxK+nume+Z9Sb4znbUKkWl+vgQATdRUEyhT2P+Gqrd0UBzYfQIDAQAB
o4IBRTCCAUEwDAYDVR0TBAUwAwEB/zAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBH
ZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFNf0xkZ3zjcEI60pVPuwDqTM
QygZMIHjBgNVHSMEgdswgdiAFP7k7FMk8JWVxxC14US1XTllWuN+oYG0pIGxMIGu
MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTE9MDsGA1UEChM0WE1M
IFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20veG1sc2Vj
KTEQMA4GA1UECxMHUm9vdCBDQTEWMBQGA1UEAxMNQWxla3NleSBTYW5pbjEhMB8G
CSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tggkAr6KLuTOt2q0wDQYJKoZI
hvcNAQEFBQADQQAOXBj0yICp1RmHXqnUlsppryLCW3pKBD1dkb4HWarO7RjA1yJJ
fBjXssrERn05kpBcrRfzou4r3DCgQFPhjxga
-----END CERTIFICATE-----

View File

@@ -11,6 +11,21 @@ type Method struct {
Algorithm string `xml:",attr"`
}
// Reference data struct
type Reference struct {
URI string `xml:"URI,attr"`
ReferenceTransforms []Method `xml:"Transforms>Transform"`
DigestMethod Method `xml:"DigestMethod"`
DigestValue string `xml:"DigestValue"`
}
// SignedInfo struct
type SignedInfo struct {
CanonicalizationMethod Method `xml:"CanonicalizationMethod"`
SignatureMethod Method `xml:"SignatureMethod"`
Reference Reference `xml:"Reference"`
}
// Signature is a model for the Signature object specified by XMLDSIG. This is
// convenience object when constructing XML that you'd like to sign. For example:
//
@@ -24,17 +39,7 @@ type Method struct {
// buf, _ := xml.Marshal(f)
// buf, _ = Sign(key, buf)
//
type Reference struct {
URI string `xml:",attr"`
Transforms []Method `xml:"Transforms>Transform"`
DigestMethod Method
DigestValue string
}
type SignedInfo struct {
CanonicalizationMethod Method `xml:"CanonicalizationMethod"`
SignatureMethod Method `xml:"SignatureMethod"`
Reference Reference
}
type Signature struct {
XMLName xml.Name `xml:"http://www.w3.org/2000/09/xmldsig# Signature"`
SignedInfo SignedInfo
@@ -65,7 +70,7 @@ func DefaultSignature(pemEncodedPublicKey []byte) Signature {
},
Reference: Reference{
Transforms: []Method{
Method{Algorithm: "http://www.w3.org/2000/09/xmldsig#enveloped-signature"},
{Algorithm: "http://www.w3.org/2000/09/xmldsig#enveloped-signature"},
},
DigestMethod: Method{
Algorithm: "http://www.w3.org/2000/09/xmldsig#sha1",

View File

@@ -9,5 +9,6 @@ import "C"
func getThreadID() uintptr {
// Darwin lacks a meaningful version of gettid() so instead we use
// ptread_self() as a proxy.
// #nosec
return uintptr(unsafe.Pointer(C.pthread_self()))
}

View File

@@ -5,12 +5,36 @@ import (
"unsafe"
)
// #include <xmlsec/xmlsec.h>
// #include <xmlsec/xmltree.h>
// #include <xmlsec/xmlenc.h>
// #include <xmlsec/xmldsig.h>
// #include <xmlsec/errors.h>
// #include <xmlsec/crypto.h>
/*
#include <xmlsec/xmlsec.h>
#include <xmlsec/xmltree.h>
#include <xmlsec/xmlenc.h>
#include <xmlsec/xmldsig.h>
#include <xmlsec/errors.h>
#include <xmlsec/crypto.h>
#include <xmlsec/nodeset.h>
#include <libxml/list.h>
void
xmlSecFindNodes(const xmlListPtr found, const xmlNodePtr parent, const xmlChar *name, const xmlChar *ns) {
xmlNodePtr cur;
xmlNodePtr ret;
xmlSecAssert2(name != NULL, NULL);
cur = parent;
while(cur != NULL) {
if(cur->children != NULL) {
xmlSecFindNodes(found, cur->children, name, ns);
}
if((cur->type == XML_ELEMENT_NODE) && xmlSecCheckNodeName(cur, name, ns)) {
xmlListPushFront(found, cur);
}
cur = cur->next;
}
}
*/
import "C"
// SignatureOptions represents additional, less commonly used, options for Sign and
@@ -42,36 +66,58 @@ 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),
// #nosec
found := C.xmlListCreate(nil, nil)
defer func() { C.xmlListDelete(found) }()
C.xmlSecFindNodes(
found,
C.xmlDocGetRootElement(parsedDoc),
(*C.xmlChar)(unsafe.Pointer(&C.xmlSecNodeSignature)),
(*C.xmlChar)(unsafe.Pointer(&C.xmlSecDSigNs)))
if node == nil {
c := C.xmlListSize(found)
if c == 0 {
return nil, errors.New("cannot find start node")
}
if rv := C.xmlSecDSigCtxSign(ctx, node); rv < 0 {
return nil, errors.New("failed to sign")
for C.xmlListEmpty(found) == 0 {
link := C.xmlListFront(found)
if link == nil {
return nil, errors.New("Link is null")
}
node := (C.xmlNodePtr)(C.xmlLinkGetData(link))
if node != nil {
ctx := C.xmlSecDSigCtxCreate(nil)
if ctx == nil {
return nil, errors.New("failed to create signature context")
}
defer C.xmlSecDSigCtxDestroy(ctx)
// #nosec
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")
}
if rv := C.xmlSecDSigCtxSign(ctx, node); rv < 0 {
return nil, errors.New("failed to sign")
}
}
C.xmlListPopFront(found)
}
return dumpDoc(parsedDoc), nil
@@ -106,6 +152,7 @@ func Verify(publicKey []byte, doc []byte, opts SignatureOptions) error {
return mustPopError()
}
// #nosec
key := C.xmlSecCryptoAppKeyLoadMemory(
(*C.xmlSecByte)(unsafe.Pointer(&publicKey[0])),
C.xmlSecSize(len(publicKey)),
@@ -115,6 +162,7 @@ func Verify(publicKey []byte, doc []byte, opts SignatureOptions) error {
return mustPopError()
}
// #nosec
if rv := C.xmlSecCryptoAppKeyCertLoadMemory(key,
(*C.xmlSecByte)(unsafe.Pointer(&publicKey[0])),
C.xmlSecSize(len(publicKey)),
@@ -127,31 +175,48 @@ func Verify(publicKey []byte, doc []byte, opts SignatureOptions) error {
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),
// #nosec
found := C.xmlListCreate(nil, nil)
defer func() { C.xmlListDelete(found) }()
C.xmlSecFindNodes(
found,
C.xmlDocGetRootElement(parsedDoc),
(*C.xmlChar)(unsafe.Pointer(&C.xmlSecNodeSignature)),
(*C.xmlChar)(unsafe.Pointer(&C.xmlSecDSigNs)))
if node == nil {
c := C.xmlListSize(found)
if c == 0 {
return errors.New("cannot find start node")
}
if rv := C.xmlSecDSigCtxVerify(dsigCtx, node); rv < 0 {
return ErrVerificationFailed
}
for C.xmlListEmpty(found) == 0 {
link := C.xmlListFront(found)
if link == nil {
break
}
node := (C.xmlNodePtr)(C.xmlLinkGetData(link))
if node != nil {
ctx := C.xmlSecDSigCtxCreate(keysMngr)
if ctx == nil {
return mustPopError()
}
defer C.xmlSecDSigCtxDestroy(ctx)
if dsigCtx.status != xmlSecDSigStatusSucceeded {
return ErrVerificationFailed
if rv := C.xmlSecDSigCtxVerify(ctx, node); rv < 0 {
return ErrVerificationFailed
}
if ctx.status != xmlSecDSigStatusSucceeded {
return ErrVerificationFailed
}
}
C.xmlListPopFront(found)
}
return nil
}

View File

@@ -2,9 +2,8 @@ package xmlsec
import (
"encoding/xml"
"strings"
. "gopkg.in/check.v1"
"strings"
)
type Envelope struct {
@@ -163,6 +162,207 @@ fBjXssrERn05kpBcrRfzou4r3DCgQFPhjxga</X509Certificate>
c.Assert(err, IsNil)
}
func (testSuite *XMLDSigTest) TestSignAndVerifyMultiple(c *C) {
expectedSignedString := `<?xml version="1.0"?>
<Envelope xmlns="urn:envelope">
<Data1 ID="id1">
Hello, World!
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#id1">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>ixa7UpgiS2UJ37IG9HzhfK7z+Fo=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>xaMgajZ9tBswZmIP5JoBwXMpD9W74fVbfWJ/HkfTHYkXNejOXT+UocvaGaVCqPNE
+6rzavcVq18agibmYCkm6w==</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIDpzCCA1GgAwIBAgIJAK+ii7kzrdqvMA0GCSqGSIb3DQEBBQUAMIGcMQswCQYD
VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3Vy
aXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEWMBQG
A1UEAxMNQWxla3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtz
ZXkuY29tMCAXDTE0MDUyMzE3NTUzNFoYDzIxMTQwNDI5MTc1NTM0WjCBxzELMAkG
A1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1
cml0eSBMaWJyYXJ5IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxKTAn
BgNVBAsTIFRlc3QgVGhpcmQgTGV2ZWwgUlNBIENlcnRpZmljYXRlMRYwFAYDVQQD
Ew1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5j
b20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEA09BtD3aeVt6DVDkk0dI7Vh7Ljqdn
sYmW0tbDVxxK+nume+Z9Sb4znbUKkWl+vgQATdRUEyhT2P+Gqrd0UBzYfQIDAQAB
o4IBRTCCAUEwDAYDVR0TBAUwAwEB/zAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBH
ZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFNf0xkZ3zjcEI60pVPuwDqTM
QygZMIHjBgNVHSMEgdswgdiAFP7k7FMk8JWVxxC14US1XTllWuN+oYG0pIGxMIGu
MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTE9MDsGA1UEChM0WE1M
IFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20veG1sc2Vj
KTEQMA4GA1UECxMHUm9vdCBDQTEWMBQGA1UEAxMNQWxla3NleSBTYW5pbjEhMB8G
CSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tggkAr6KLuTOt2q0wDQYJKoZI
hvcNAQEFBQADQQAOXBj0yICp1RmHXqnUlsppryLCW3pKBD1dkb4HWarO7RjA1yJJ
fBjXssrERn05kpBcrRfzou4r3DCgQFPhjxga</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
<Data2 ID="id2">
Hello, World!
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#id2">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>6hs7C+iZA45BBGAcaI0aNnMz+Ts=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>F23IldNw0Gozri5ySU5Esopz7llkBrDJNHNgm+Ww93mrU5w1IrP0J7Cv0Xn19ro2
QsO3oBVrpdMotMsFkbEVkA==</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIDpzCCA1GgAwIBAgIJAK+ii7kzrdqvMA0GCSqGSIb3DQEBBQUAMIGcMQswCQYD
VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3Vy
aXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEWMBQG
A1UEAxMNQWxla3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtz
ZXkuY29tMCAXDTE0MDUyMzE3NTUzNFoYDzIxMTQwNDI5MTc1NTM0WjCBxzELMAkG
A1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1
cml0eSBMaWJyYXJ5IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxKTAn
BgNVBAsTIFRlc3QgVGhpcmQgTGV2ZWwgUlNBIENlcnRpZmljYXRlMRYwFAYDVQQD
Ew1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5j
b20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEA09BtD3aeVt6DVDkk0dI7Vh7Ljqdn
sYmW0tbDVxxK+nume+Z9Sb4znbUKkWl+vgQATdRUEyhT2P+Gqrd0UBzYfQIDAQAB
o4IBRTCCAUEwDAYDVR0TBAUwAwEB/zAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBH
ZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFNf0xkZ3zjcEI60pVPuwDqTM
QygZMIHjBgNVHSMEgdswgdiAFP7k7FMk8JWVxxC14US1XTllWuN+oYG0pIGxMIGu
MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTE9MDsGA1UEChM0WE1M
IFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20veG1sc2Vj
KTEQMA4GA1UECxMHUm9vdCBDQTEWMBQGA1UEAxMNQWxla3NleSBTYW5pbjEhMB8G
CSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tggkAr6KLuTOt2q0wDQYJKoZI
hvcNAQEFBQADQQAOXBj0yICp1RmHXqnUlsppryLCW3pKBD1dkb4HWarO7RjA1yJJ
fBjXssrERn05kpBcrRfzou4r3DCgQFPhjxga</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</Data2>
</Data1>
</Envelope>
`
actualUnsignedString := `
<Envelope xmlns="urn:envelope">
<Data1 ID="id1">
Hello, World!
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#id1">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue/>
</Reference>
</SignedInfo>
<SignatureValue/>
<KeyInfo>
<X509Data>
<X509Certificate>MIIDpzCCA1GgAwIBAgIJAK+ii7kzrdqvMA0GCSqGSIb3DQEBBQUAMIGcMQswCQYD
VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3Vy
aXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEWMBQG
A1UEAxMNQWxla3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtz
ZXkuY29tMCAXDTE0MDUyMzE3NTUzNFoYDzIxMTQwNDI5MTc1NTM0WjCBxzELMAkG
A1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1
cml0eSBMaWJyYXJ5IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxKTAn
BgNVBAsTIFRlc3QgVGhpcmQgTGV2ZWwgUlNBIENlcnRpZmljYXRlMRYwFAYDVQQD
Ew1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5j
b20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEA09BtD3aeVt6DVDkk0dI7Vh7Ljqdn
sYmW0tbDVxxK+nume+Z9Sb4znbUKkWl+vgQATdRUEyhT2P+Gqrd0UBzYfQIDAQAB
o4IBRTCCAUEwDAYDVR0TBAUwAwEB/zAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBH
ZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFNf0xkZ3zjcEI60pVPuwDqTM
QygZMIHjBgNVHSMEgdswgdiAFP7k7FMk8JWVxxC14US1XTllWuN+oYG0pIGxMIGu
MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTE9MDsGA1UEChM0WE1M
IFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20veG1sc2Vj
KTEQMA4GA1UECxMHUm9vdCBDQTEWMBQGA1UEAxMNQWxla3NleSBTYW5pbjEhMB8G
CSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tggkAr6KLuTOt2q0wDQYJKoZI
hvcNAQEFBQADQQAOXBj0yICp1RmHXqnUlsppryLCW3pKBD1dkb4HWarO7RjA1yJJ
fBjXssrERn05kpBcrRfzou4r3DCgQFPhjxga</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
<Data2 ID="id2">
Hello, World!
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#id2">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue/>
</Reference>
</SignedInfo>
<SignatureValue/>
<KeyInfo>
<X509Data>
<X509Certificate>MIIDpzCCA1GgAwIBAgIJAK+ii7kzrdqvMA0GCSqGSIb3DQEBBQUAMIGcMQswCQYD
VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3Vy
aXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEWMBQG
A1UEAxMNQWxla3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtz
ZXkuY29tMCAXDTE0MDUyMzE3NTUzNFoYDzIxMTQwNDI5MTc1NTM0WjCBxzELMAkG
A1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1
cml0eSBMaWJyYXJ5IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxKTAn
BgNVBAsTIFRlc3QgVGhpcmQgTGV2ZWwgUlNBIENlcnRpZmljYXRlMRYwFAYDVQQD
Ew1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5j
b20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEA09BtD3aeVt6DVDkk0dI7Vh7Ljqdn
sYmW0tbDVxxK+nume+Z9Sb4znbUKkWl+vgQATdRUEyhT2P+Gqrd0UBzYfQIDAQAB
o4IBRTCCAUEwDAYDVR0TBAUwAwEB/zAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBH
ZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFNf0xkZ3zjcEI60pVPuwDqTM
QygZMIHjBgNVHSMEgdswgdiAFP7k7FMk8JWVxxC14US1XTllWuN+oYG0pIGxMIGu
MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTE9MDsGA1UEChM0WE1M
IFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20veG1sc2Vj
KTEQMA4GA1UECxMHUm9vdCBDQTEWMBQGA1UEAxMNQWxla3NleSBTYW5pbjEhMB8G
CSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tggkAr6KLuTOt2q0wDQYJKoZI
hvcNAQEFBQADQQAOXBj0yICp1RmHXqnUlsppryLCW3pKBD1dkb4HWarO7RjA1yJJ
fBjXssrERn05kpBcrRfzou4r3DCgQFPhjxga</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</Data2>
</Data1>
</Envelope>
`
opts := SignatureOptions{XMLID: []XMLIDOption{
{ElementName: "Data1", AttributeName: "ID"},
{ElementName: "Data2", AttributeName: "ID"},
}}
actualSignedString, err := Sign(testSuite.Key, []byte(actualUnsignedString), opts)
c.Assert(err, IsNil)
c.Assert(string(actualSignedString), Equals, expectedSignedString)
err = Verify(testSuite.Cert, actualSignedString, opts)
c.Assert(err, IsNil)
data1Sig := `<SignatureValue>xaMgajZ9tBswZmIP5JoBwXMpD9W74fVbfWJ/HkfTHYkXNejOXT+UocvaGaVCqPNE
+6rzavcVq18agibmYCkm6w==</SignatureValue>`
data2Sig := `<SignatureValue>F23IldNw0Gozri5ySU5Esopz7llkBrDJNHNgm+Ww93mrU5w1IrP0J7Cv0Xn19ro2
QsO3oBVrpdMotMsFkbEVkA==</SignatureValue>`
breakData1 := strings.Replace(expectedSignedString, data1Sig, data2Sig, 1)
err = Verify(testSuite.Cert, []byte(breakData1), opts)
c.Assert(err, ErrorMatches, "signature verification failed")
breakData2 := strings.Replace(expectedSignedString, data2Sig, data1Sig, 1)
err = Verify(testSuite.Cert, []byte(breakData2), opts)
c.Assert(err, ErrorMatches, "signature verification failed")
}
func (testSuite *XMLDSigTest) TestConstructFromSignature(c *C) {
// Try again but this time construct the message from a struct having a Signature member
doc := Envelope{Data: "Hello, World!"}
@@ -179,7 +379,7 @@ func (testSuite *XMLDSigTest) TestConstructFromSignature(c *C) {
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference>
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
@@ -187,8 +387,8 @@ func (testSuite *XMLDSigTest) TestConstructFromSignature(c *C) {
<DigestValue>sEenIPkW9ssFSB9t4UU6VUrytqc=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>chSWfpQBIQraySsUHzs5N51+ruelu2HMHh5Mnd3EjcLqFBVD0f23kmXUp7zVhCVD
vCfqu9yXDYKVOBI57F0Efg==</SignatureValue>
<SignatureValue>xGbrj3FkyalDesH7R8xS41i5w69sM9WvuFmPeJ/LQ1zIjHoeHBq4SRzTOPg9xgjj
YYGrWwpJY9khPQsfwjwWTQ==</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIDpzCCA1GgAwIBAgIJAK+ii7kzrdqvMA0GCSqGSIb3DQEBBQUAMIGcMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEWMBQGA1UEAxMNQWxla3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tMCAXDTE0MDUyMzE3NTUzNFoYDzIxMTQwNDI5MTc1NTM0WjCBxzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1cml0eSBMaWJyYXJ5IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxKTAnBgNVBAsTIFRlc3QgVGhpcmQgTGV2ZWwgUlNBIENlcnRpZmljYXRlMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEA09BtD3aeVt6DVDkk0dI7Vh7LjqdnsYmW0tbDVxxK+nume+Z9Sb4znbUKkWl+vgQATdRUEyhT2P+Gqrd0UBzYfQIDAQABo4IBRTCCAUEwDAYDVR0TBAUwAwEB/zAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFNf0xkZ3zjcEI60pVPuwDqTMQygZMIHjBgNVHSMEgdswgdiAFP7k7FMk8JWVxxC14US1XTllWuN+oYG0pIGxMIGuMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEQMA4GA1UECxMHUm9vdCBDQTEWMBQGA1UEAxMNQWxla3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tggkAr6KLuTOt2q0wDQYJKoZIhvcNAQEFBQADQQAOXBj0yICp1RmHXqnUlsppryLCW3pKBD1dkb4HWarO7RjA1yJJfBjXssrERn05kpBcrRfzou4r3DCgQFPhjxga</X509Certificate>
@@ -197,6 +397,7 @@ vCfqu9yXDYKVOBI57F0Efg==</SignatureValue>
</Signature>
</Envelope>
`
c.Assert(string(actualSignedString), Equals, expectedSignedString)
err = Verify(testSuite.Cert, actualSignedString, SignatureOptions{})

View File

@@ -42,6 +42,7 @@ func init() {
}
func newDoc(buf []byte, idattrs []XMLIDOption) (*C.xmlDoc, error) {
// #nosec
ctx := C.xmlCreateMemoryParserCtxt((*C.char)(unsafe.Pointer(&buf[0])),
C.int(len(buf)))
if ctx == nil {
@@ -78,15 +79,18 @@ func addIDAttr(node *C.xmlNode, attrName, nodeName, nsHref string) {
cur = C.xmlSecGetNextElementNode(cur.next)
}
// #nosec
if C.GoString((*C.char)(unsafe.Pointer(node.name))) != nodeName {
return
}
// #nosec
if nsHref != "" && node.ns != nil && C.GoString((*C.char)(unsafe.Pointer(node.ns.href))) != nsHref {
return
}
// the attribute with name equal to attrName should exist
for attr := node.properties; attr != nil; attr = attr.next {
// #nosec
if C.GoString((*C.char)(unsafe.Pointer(attr.name))) == attrName {
id := C.xmlNodeListGetString(node.doc, attr.children, 1)
if id == nil {
@@ -106,7 +110,15 @@ func dumpDoc(doc *C.xmlDoc) []byte {
var buffer *C.xmlChar
var bufferSize C.int
C.xmlDocDumpMemory(doc, &buffer, &bufferSize)
defer C.MY_xmlFree(unsafe.Pointer(buffer))
defer C.MY_xmlFree(unsafe.Pointer(buffer)) // #nosec
return C.GoBytes(unsafe.Pointer(buffer), bufferSize)
return C.GoBytes(unsafe.Pointer(buffer), bufferSize) // #nosec
}
func dumpNode(node *C.xmlNode) []byte {
buffer := C.xmlBufferCreate()
defer C.xmlBufferFree(buffer)
bufferSize := C.xmlNodeDump(buffer, nil, node, 0, 0)
return C.GoBytes(unsafe.Pointer(buffer.content), bufferSize) // #nosec
}