Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
D
dex
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
dex
Commits
4b457d8c
Commit
4b457d8c
authored
Mar 24, 2017
by
Phu Kieu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
vendor: revendor
parent
b5f70dac
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
532 additions
and
258 deletions
+532
-258
glide.lock
glide.lock
+4
-3
canonicalize.go
vendor/github.com/russellhaering/goxmldsig/canonicalize.go
+9
-101
canonicalize.go
...b.com/russellhaering/goxmldsig/etreeutils/canonicalize.go
+98
-0
namespace.go
...thub.com/russellhaering/goxmldsig/etreeutils/namespace.go
+107
-31
sort.go
...or/github.com/russellhaering/goxmldsig/etreeutils/sort.go
+29
-6
unmarshal.go
...thub.com/russellhaering/goxmldsig/etreeutils/unmarshal.go
+43
-0
sign.go
vendor/github.com/russellhaering/goxmldsig/sign.go
+30
-5
signature.go
...or/github.com/russellhaering/goxmldsig/types/signature.go
+93
-0
validate.go
vendor/github.com/russellhaering/goxmldsig/validate.go
+119
-112
No files found.
glide.lock
View file @
4b457d8c
hash:
4a3ac3a2a2b39357dc5de7ba296dbe20a97dd2fe13bc15a68e904e69afae2adb
hash:
ba77a77f03b1750479aa4a61de59d7a545dc8bd5c71be10e1c2e9afed37e1925
updated: 2017-03-2
1T09:24:08.089284929
-07:00
updated: 2017-03-2
4T11:03:21.332291207
-07:00
imports:
imports:
- name: github.com/beevik/etree
- name: github.com/beevik/etree
version: 4cd0dd976db869f817248477718071a28e978df0
version: 4cd0dd976db869f817248477718071a28e978df0
...
@@ -46,9 +46,10 @@ imports:
...
@@ -46,9 +46,10 @@ imports:
subpackages:
subpackages:
- cacheobject
- cacheobject
- name: github.com/russellhaering/goxmldsig
- name: github.com/russellhaering/goxmldsig
version:
51810e925e5fc495822fbddda8202f70a6e4a3f3
version:
eaac44c63fe007124f8f6255b09febc906784981
subpackages:
subpackages:
- etreeutils
- etreeutils
- types
- name: github.com/Sirupsen/logrus
- name: github.com/Sirupsen/logrus
version: d26492970760ca5d33129d2d799e34be5c4782eb
version: d26492970760ca5d33129d2d799e34be5c4782eb
- name: github.com/spf13/cobra
- name: github.com/spf13/cobra
...
...
vendor/github.com/russellhaering/goxmldsig/canonicalize.go
View file @
4b457d8c
...
@@ -2,7 +2,6 @@ package dsig
...
@@ -2,7 +2,6 @@ package dsig
import
(
import
(
"sort"
"sort"
"strings"
"github.com/beevik/etree"
"github.com/beevik/etree"
"github.com/russellhaering/goxmldsig/etreeutils"
"github.com/russellhaering/goxmldsig/etreeutils"
...
@@ -15,28 +14,25 @@ type Canonicalizer interface {
...
@@ -15,28 +14,25 @@ type Canonicalizer interface {
}
}
type
c14N10ExclusiveCanonicalizer
struct
{
type
c14N10ExclusiveCanonicalizer
struct
{
InclusiveNamespaces
map
[
string
]
struct
{}
prefixList
string
}
}
// MakeC14N10ExclusiveCanonicalizerWithPrefixList constructs an exclusive Canonicalizer
// MakeC14N10ExclusiveCanonicalizerWithPrefixList constructs an exclusive Canonicalizer
// from a PrefixList in NMTOKENS format (a white space separated list).
// from a PrefixList in NMTOKENS format (a white space separated list).
func
MakeC14N10ExclusiveCanonicalizerWithPrefixList
(
prefixList
string
)
Canonicalizer
{
func
MakeC14N10ExclusiveCanonicalizerWithPrefixList
(
prefixList
string
)
Canonicalizer
{
prefixes
:=
strings
.
Fields
(
prefixList
)
prefixSet
:=
make
(
map
[
string
]
struct
{},
len
(
prefixes
))
for
_
,
prefix
:=
range
prefixes
{
prefixSet
[
prefix
]
=
struct
{}{}
}
return
&
c14N10ExclusiveCanonicalizer
{
return
&
c14N10ExclusiveCanonicalizer
{
InclusiveNamespaces
:
prefixSe
t
,
prefixList
:
prefixLis
t
,
}
}
}
}
// Canonicalize transforms the input Element into a serialized XML document in canonical form.
// Canonicalize transforms the input Element into a serialized XML document in canonical form.
func
(
c
*
c14N10ExclusiveCanonicalizer
)
Canonicalize
(
el
*
etree
.
Element
)
([]
byte
,
error
)
{
func
(
c
*
c14N10ExclusiveCanonicalizer
)
Canonicalize
(
el
*
etree
.
Element
)
([]
byte
,
error
)
{
scope
:=
make
(
map
[
string
]
c14nSpace
)
err
:=
etreeutils
.
TransformExcC14n
(
el
,
c
.
prefixList
)
return
canonicalSerialize
(
excCanonicalPrep
(
el
,
scope
,
c
.
InclusiveNamespaces
))
if
err
!=
nil
{
return
nil
,
err
}
return
canonicalSerialize
(
el
)
}
}
func
(
c
*
c14N10ExclusiveCanonicalizer
)
Algorithm
()
AlgorithmID
{
func
(
c
*
c14N10ExclusiveCanonicalizer
)
Algorithm
()
AlgorithmID
{
...
@@ -75,94 +71,6 @@ type c14nSpace struct {
...
@@ -75,94 +71,6 @@ type c14nSpace struct {
const
nsSpace
=
"xmlns"
const
nsSpace
=
"xmlns"
// excCanonicalPrep accepts an *etree.Element and recursively transforms it into one
// which is ready for serialization to exclusive canonical form. Specifically this
// entails:
//
// 1. Stripping re-declarations of namespaces
// 2. Stripping unused namespaces
// 3. Sorting attributes into canonical order.
//
// NOTE(russell_h): Currently this function modifies the passed element.
func
excCanonicalPrep
(
el
*
etree
.
Element
,
_nsAlreadyDeclared
map
[
string
]
c14nSpace
,
inclusiveNamespaces
map
[
string
]
struct
{})
*
etree
.
Element
{
//Copy alreadyDeclared map (only contains namespaces)
nsAlreadyDeclared
:=
make
(
map
[
string
]
c14nSpace
,
len
(
_nsAlreadyDeclared
))
for
k
:=
range
_nsAlreadyDeclared
{
nsAlreadyDeclared
[
k
]
=
_nsAlreadyDeclared
[
k
]
}
//Track the namespaces used on the current element
nsUsedHere
:=
make
(
map
[
string
]
struct
{})
//Make sure to track the element namespace for the case:
//<foo:bar xmlns:foo="..."/>
if
el
.
Space
!=
""
{
nsUsedHere
[
el
.
Space
]
=
struct
{}{}
}
toRemove
:=
make
([]
string
,
0
,
0
)
for
_
,
a
:=
range
el
.
Attr
{
switch
a
.
Space
{
case
nsSpace
:
//For simplicity, remove all xmlns attribues; to be added in one pass
//later. Otherwise, we need another map/set to track xmlns attributes
//that we left alone.
toRemove
=
append
(
toRemove
,
a
.
Space
+
":"
+
a
.
Key
)
if
_
,
ok
:=
nsAlreadyDeclared
[
a
.
Key
];
!
ok
{
//If we're not tracking ancestor state already for this namespace, add
//it to the map
nsAlreadyDeclared
[
a
.
Key
]
=
c14nSpace
{
a
:
a
,
used
:
false
}
}
// This algorithm accepts a set of namespaces which should be treated
// in an inclusive fashion. Specifically that means we should keep the
// declaration of that namespace closest to the root of the tree. We can
// accomplish that be pretending it was used by this element.
_
,
inclusive
:=
inclusiveNamespaces
[
a
.
Key
]
if
inclusive
{
nsUsedHere
[
a
.
Key
]
=
struct
{}{}
}
default
:
//We only track namespaces, so ignore attributes without one.
if
a
.
Space
!=
""
{
nsUsedHere
[
a
.
Space
]
=
struct
{}{}
}
}
}
//Remove all attributes so that we can add them with much-simpler logic
for
_
,
attrK
:=
range
toRemove
{
el
.
RemoveAttr
(
attrK
)
}
//For all namespaces used on the current element, declare them if they were
//not declared (and used) in an ancestor.
for
k
:=
range
nsUsedHere
{
spc
:=
nsAlreadyDeclared
[
k
]
//If previously unused, mark as used
if
!
spc
.
used
{
el
.
Attr
=
append
(
el
.
Attr
,
spc
.
a
)
spc
.
used
=
true
//Assignment here is only to update the pre-existing `used` tracking value
nsAlreadyDeclared
[
k
]
=
spc
}
}
//Canonicalize all children, passing down the ancestor tracking map
for
_
,
child
:=
range
el
.
ChildElements
()
{
excCanonicalPrep
(
child
,
nsAlreadyDeclared
,
inclusiveNamespaces
)
}
//Sort attributes lexicographically
sort
.
Sort
(
etreeutils
.
SortedAttrs
(
el
.
Attr
))
return
el
.
Copy
()
}
// canonicalPrep accepts an *etree.Element and transforms it into one which is ready
// canonicalPrep accepts an *etree.Element and transforms it into one which is ready
// for serialization into inclusive canonical form. Specifically this
// for serialization into inclusive canonical form. Specifically this
// entails:
// entails:
...
@@ -208,7 +116,7 @@ func canonicalPrep(el *etree.Element, seenSoFar map[string]struct{}) *etree.Elem
...
@@ -208,7 +116,7 @@ func canonicalPrep(el *etree.Element, seenSoFar map[string]struct{}) *etree.Elem
func
canonicalSerialize
(
el
*
etree
.
Element
)
([]
byte
,
error
)
{
func
canonicalSerialize
(
el
*
etree
.
Element
)
([]
byte
,
error
)
{
doc
:=
etree
.
NewDocument
()
doc
:=
etree
.
NewDocument
()
doc
.
SetRoot
(
el
)
doc
.
SetRoot
(
el
.
Copy
()
)
doc
.
WriteSettings
=
etree
.
WriteSettings
{
doc
.
WriteSettings
=
etree
.
WriteSettings
{
CanonicalAttrVal
:
true
,
CanonicalAttrVal
:
true
,
...
...
vendor/github.com/russellhaering/goxmldsig/etreeutils/canonicalize.go
0 → 100644
View file @
4b457d8c
package
etreeutils
import
(
"sort"
"strings"
"github.com/beevik/etree"
)
// TransformExcC14n transforms the passed element into xml-exc-c14n form.
func
TransformExcC14n
(
el
*
etree
.
Element
,
inclusiveNamespacesPrefixList
string
)
error
{
prefixes
:=
strings
.
Fields
(
inclusiveNamespacesPrefixList
)
prefixSet
:=
make
(
map
[
string
]
struct
{},
len
(
prefixes
))
for
_
,
prefix
:=
range
prefixes
{
prefixSet
[
prefix
]
=
struct
{}{}
}
err
:=
transformExcC14n
(
DefaultNSContext
,
EmptyNSContext
,
el
,
prefixSet
)
if
err
!=
nil
{
return
err
}
return
nil
}
func
transformExcC14n
(
ctx
,
declared
NSContext
,
el
*
etree
.
Element
,
inclusiveNamespaces
map
[
string
]
struct
{})
error
{
scope
,
err
:=
ctx
.
SubContext
(
el
)
if
err
!=
nil
{
return
err
}
visiblyUtilizedPrefixes
:=
map
[
string
]
struct
{}{
el
.
Space
:
struct
{}{},
}
filteredAttrs
:=
[]
etree
.
Attr
{}
// Filter out all namespace declarations
for
_
,
attr
:=
range
el
.
Attr
{
switch
{
case
attr
.
Space
==
xmlnsPrefix
:
if
_
,
ok
:=
inclusiveNamespaces
[
attr
.
Key
];
ok
{
visiblyUtilizedPrefixes
[
attr
.
Key
]
=
struct
{}{}
}
case
attr
.
Space
==
defaultPrefix
&&
attr
.
Key
==
xmlnsPrefix
:
if
_
,
ok
:=
inclusiveNamespaces
[
defaultPrefix
];
ok
{
visiblyUtilizedPrefixes
[
defaultPrefix
]
=
struct
{}{}
}
default
:
if
attr
.
Space
!=
defaultPrefix
{
visiblyUtilizedPrefixes
[
attr
.
Space
]
=
struct
{}{}
}
filteredAttrs
=
append
(
filteredAttrs
,
attr
)
}
}
el
.
Attr
=
filteredAttrs
declared
=
declared
.
Copy
()
// Declare all visibly utilized prefixes that are in-scope but haven't
// been declared in the canonicalized form yet. These might have been
// declared on this element but then filtered out above, or they might
// have been declared on an ancestor (before canonicalization) which
// didn't visibly utilize and thus had them removed.
for
prefix
:=
range
visiblyUtilizedPrefixes
{
// Skip redundant declarations - they have to already have the same
// value.
if
declaredNamespace
,
ok
:=
declared
.
prefixes
[
prefix
];
ok
{
if
value
,
ok
:=
scope
.
prefixes
[
prefix
];
ok
&&
declaredNamespace
==
value
{
continue
}
}
namespace
,
err
:=
scope
.
LookupPrefix
(
prefix
)
if
err
!=
nil
{
return
err
}
el
.
Attr
=
append
(
el
.
Attr
,
declared
.
declare
(
prefix
,
namespace
))
}
sort
.
Sort
(
SortedAttrs
(
el
.
Attr
))
// Transform child elements
for
_
,
child
:=
range
el
.
ChildElements
()
{
err
:=
transformExcC14n
(
scope
,
declared
,
child
,
inclusiveNamespaces
)
if
err
!=
nil
{
return
err
}
}
return
nil
}
vendor/github.com/russellhaering/goxmldsig/etreeutils/namespace.go
View file @
4b457d8c
...
@@ -47,13 +47,38 @@ type NSContext struct {
...
@@ -47,13 +47,38 @@ type NSContext struct {
prefixes
map
[
string
]
string
prefixes
map
[
string
]
string
}
}
func
(
ctx
NSContext
)
SubContext
(
el
*
etree
.
Element
)
(
NSContext
,
error
)
{
func
(
ctx
NSContext
)
Copy
()
NSContext
{
// The subcontext should inherit existing declared prefixes
prefixes
:=
make
(
map
[
string
]
string
,
len
(
ctx
.
prefixes
)
+
4
)
prefixes
:=
make
(
map
[
string
]
string
,
len
(
ctx
.
prefixes
)
+
4
)
for
k
,
v
:=
range
ctx
.
prefixes
{
for
k
,
v
:=
range
ctx
.
prefixes
{
prefixes
[
k
]
=
v
prefixes
[
k
]
=
v
}
}
return
NSContext
{
prefixes
:
prefixes
}
}
func
(
ctx
NSContext
)
declare
(
prefix
,
namespace
string
)
etree
.
Attr
{
ctx
.
prefixes
[
prefix
]
=
namespace
switch
prefix
{
case
defaultPrefix
:
return
etree
.
Attr
{
Key
:
xmlnsPrefix
,
Value
:
namespace
,
}
default
:
return
etree
.
Attr
{
Space
:
xmlnsPrefix
,
Key
:
prefix
,
Value
:
namespace
,
}
}
}
func
(
ctx
NSContext
)
SubContext
(
el
*
etree
.
Element
)
(
NSContext
,
error
)
{
// The subcontext should inherit existing declared prefixes
newCtx
:=
ctx
.
Copy
()
// Merge new namespace declarations on top of existing ones.
// Merge new namespace declarations on top of existing ones.
for
_
,
attr
:=
range
el
.
Attr
{
for
_
,
attr
:=
range
el
.
Attr
{
if
attr
.
Space
==
xmlnsPrefix
{
if
attr
.
Space
==
xmlnsPrefix
{
...
@@ -69,7 +94,7 @@ func (ctx NSContext) SubContext(el *etree.Element) (NSContext, error) {
...
@@ -69,7 +94,7 @@ func (ctx NSContext) SubContext(el *etree.Element) (NSContext, error) {
return
ctx
,
ErrReservedNamespace
return
ctx
,
ErrReservedNamespace
}
}
prefixes
[
attr
.
Key
]
=
attr
.
Value
newCtx
.
declare
(
attr
.
Key
,
attr
.
Value
)
}
else
if
attr
.
Space
==
defaultPrefix
&&
attr
.
Key
==
xmlnsPrefix
{
}
else
if
attr
.
Space
==
defaultPrefix
&&
attr
.
Key
==
xmlnsPrefix
{
// This attribute is a default namespace declaration
// This attribute is a default namespace declaration
...
@@ -78,11 +103,21 @@ func (ctx NSContext) SubContext(el *etree.Element) (NSContext, error) {
...
@@ -78,11 +103,21 @@ func (ctx NSContext) SubContext(el *etree.Element) (NSContext, error) {
return
ctx
,
ErrInvalidDefaultNamespace
return
ctx
,
ErrInvalidDefaultNamespace
}
}
prefixes
[
defaultPrefix
]
=
attr
.
Value
newCtx
.
declare
(
defaultPrefix
,
attr
.
Value
)
}
}
}
}
return
NSContext
{
prefixes
:
prefixes
},
nil
return
newCtx
,
nil
}
// Prefixes returns a copy of this context's prefix map.
func
(
ctx
NSContext
)
Prefixes
()
map
[
string
]
string
{
prefixes
:=
make
(
map
[
string
]
string
,
len
(
ctx
.
prefixes
))
for
k
,
v
:=
range
ctx
.
prefixes
{
prefixes
[
k
]
=
v
}
return
prefixes
}
}
// LookupPrefix attempts to find a declared namespace for the specified prefix. If the prefix
// LookupPrefix attempts to find a declared namespace for the specified prefix. If the prefix
...
@@ -98,7 +133,13 @@ func (ctx NSContext) LookupPrefix(prefix string) (string, error) {
...
@@ -98,7 +133,13 @@ func (ctx NSContext) LookupPrefix(prefix string) (string, error) {
}
}
}
}
func
nsTraverse
(
ctx
NSContext
,
el
*
etree
.
Element
,
handle
func
(
NSContext
,
*
etree
.
Element
)
error
)
error
{
// NSIterHandler is a function which is invoked with a element and its surrounding
// NSContext during traversals.
type
NSIterHandler
func
(
NSContext
,
*
etree
.
Element
)
error
// NSTraverse traverses an element tree, invoking the passed handler for each element
// in the tree.
func
NSTraverse
(
ctx
NSContext
,
el
*
etree
.
Element
,
handle
NSIterHandler
)
error
{
ctx
,
err
:=
ctx
.
SubContext
(
el
)
ctx
,
err
:=
ctx
.
SubContext
(
el
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
...
@@ -111,7 +152,7 @@ func nsTraverse(ctx NSContext, el *etree.Element, handle func(NSContext, *etree.
...
@@ -111,7 +152,7 @@ func nsTraverse(ctx NSContext, el *etree.Element, handle func(NSContext, *etree.
// Recursively traverse child elements.
// Recursively traverse child elements.
for
_
,
child
:=
range
el
.
ChildElements
()
{
for
_
,
child
:=
range
el
.
ChildElements
()
{
err
:=
ns
Traverse
(
ctx
,
child
,
handle
)
err
:=
NS
Traverse
(
ctx
,
child
,
handle
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -120,7 +161,9 @@ func nsTraverse(ctx NSContext, el *etree.Element, handle func(NSContext, *etree.
...
@@ -120,7 +161,9 @@ func nsTraverse(ctx NSContext, el *etree.Element, handle func(NSContext, *etree.
return
nil
return
nil
}
}
func
detachWithNamespaces
(
ctx
NSContext
,
el
*
etree
.
Element
)
(
*
etree
.
Element
,
error
)
{
// NSDetatch makes a copy of the passed element, and declares any namespaces in
// the passed context onto the new element before returning it.
func
NSDetatch
(
ctx
NSContext
,
el
*
etree
.
Element
)
(
*
etree
.
Element
,
error
)
{
ctx
,
err
:=
ctx
.
SubContext
(
el
)
ctx
,
err
:=
ctx
.
SubContext
(
el
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -177,43 +220,52 @@ func detachWithNamespaces(ctx NSContext, el *etree.Element) (*etree.Element, err
...
@@ -177,43 +220,52 @@ func detachWithNamespaces(ctx NSContext, el *etree.Element) (*etree.Element, err
return
el
,
nil
return
el
,
nil
}
}
// NSSelectOne conducts a depth-first search for an element with the specified namespace
// NSSelectOne behaves identically to NSSelectOneCtx, but uses DefaultNSContext as the
// surrounding context.
func
NSSelectOne
(
el
*
etree
.
Element
,
namespace
,
tag
string
)
(
*
etree
.
Element
,
error
)
{
return
NSSelectOneCtx
(
DefaultNSContext
,
el
,
namespace
,
tag
)
}
// NSSelectOneCtx conducts a depth-first search for an element with the specified namespace
// and tag. If such an element is found, a new *etree.Element is returned which is a
// and tag. If such an element is found, a new *etree.Element is returned which is a
// copy of the found element, but with all in-context namespace declarations attached
// copy of the found element, but with all in-context namespace declarations attached
// to the element as attributes.
// to the element as attributes.
func
NSSelectOne
(
el
*
etree
.
Element
,
namespace
,
tag
string
)
(
*
etree
.
Element
,
error
)
{
func
NSSelectOne
Ctx
(
ctx
NSContext
,
el
*
etree
.
Element
,
namespace
,
tag
string
)
(
*
etree
.
Element
,
error
)
{
var
found
*
etree
.
Element
var
found
*
etree
.
Element
err
:=
nsTraverse
(
DefaultNSContext
,
el
,
func
(
ctx
NSContext
,
el
*
etree
.
Element
)
error
{
err
:=
NSFindIterateCtx
(
ctx
,
el
,
namespace
,
tag
,
func
(
ctx
NSContext
,
el
*
etree
.
Element
)
error
{
currentNS
,
err
:=
ctx
.
LookupPrefix
(
el
.
Space
)
var
err
error
found
,
err
=
NSDetatch
(
ctx
,
el
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
// Base case, el is the sought after element.
if
currentNS
==
namespace
&&
el
.
Tag
==
tag
{
found
,
err
=
detachWithNamespaces
(
ctx
,
el
)
return
ErrTraversalHalted
return
ErrTraversalHalted
}
return
nil
})
})
if
err
!=
nil
&&
err
!=
ErrTraversalHalted
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
return
found
,
nil
return
found
,
nil
}
}
// NSFindIterate conducts a depth-first traversal searching for elements with the
// NSFindIterate behaves identically to NSFindIterateCtx, but uses DefaultNSContext
// specified tag in the specified namespace. For each such element, the passed
// as the surrounding context.
// handler function is invoked. If the handler function returns an error
func
NSFindIterate
(
el
*
etree
.
Element
,
namespace
,
tag
string
,
handle
NSIterHandler
)
error
{
// traversal is immediately halted. If the error returned by the handler is
return
NSFindIterateCtx
(
DefaultNSContext
,
el
,
namespace
,
tag
,
handle
)
// ErrTraversalHalted then nil will be returned by NSFindIterate. If any other
}
// error is returned by the handler, that error will be returned by NSFindIterate.
func
NSFindIterate
(
el
*
etree
.
Element
,
namespace
,
tag
string
,
handle
func
(
*
etree
.
Element
)
error
)
error
{
// NSFindIterateCtx conducts a depth-first traversal searching for elements with the
err
:=
nsTraverse
(
DefaultNSContext
,
el
,
func
(
ctx
NSContext
,
el
*
etree
.
Element
)
error
{
// specified tag in the specified namespace. It uses the passed NSContext for prefix
// lookups. For each such element, the passed handler function is invoked. If the
// handler function returns an error traversal is immediately halted. If the error
// returned by the handler is ErrTraversalHalted then nil will be returned by
// NSFindIterate. If any other error is returned by the handler, that error will be
// returned by NSFindIterate.
func
NSFindIterateCtx
(
ctx
NSContext
,
el
*
etree
.
Element
,
namespace
,
tag
string
,
handle
NSIterHandler
)
error
{
err
:=
NSTraverse
(
ctx
,
el
,
func
(
ctx
NSContext
,
el
*
etree
.
Element
)
error
{
currentNS
,
err
:=
ctx
.
LookupPrefix
(
el
.
Space
)
currentNS
,
err
:=
ctx
.
LookupPrefix
(
el
.
Space
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
...
@@ -221,7 +273,7 @@ func NSFindIterate(el *etree.Element, namespace, tag string, handle func(*etree.
...
@@ -221,7 +273,7 @@ func NSFindIterate(el *etree.Element, namespace, tag string, handle func(*etree.
// Base case, el is the sought after element.
// Base case, el is the sought after element.
if
currentNS
==
namespace
&&
el
.
Tag
==
tag
{
if
currentNS
==
namespace
&&
el
.
Tag
==
tag
{
return
handle
(
el
)
return
handle
(
ctx
,
el
)
}
}
return
nil
return
nil
...
@@ -234,12 +286,18 @@ func NSFindIterate(el *etree.Element, namespace, tag string, handle func(*etree.
...
@@ -234,12 +286,18 @@ func NSFindIterate(el *etree.Element, namespace, tag string, handle func(*etree.
return
nil
return
nil
}
}
// NSFindOne
conducts a depth-first search for the specified element. If such an element
// NSFindOne
behaves identically to NSFindOneCtx, but uses DefaultNSContext for
//
is found a reference to it is returned
.
//
context
.
func
NSFindOne
(
el
*
etree
.
Element
,
namespace
,
tag
string
)
(
*
etree
.
Element
,
error
)
{
func
NSFindOne
(
el
*
etree
.
Element
,
namespace
,
tag
string
)
(
*
etree
.
Element
,
error
)
{
return
NSFindOneCtx
(
DefaultNSContext
,
el
,
namespace
,
tag
)
}
// NSFindOneCtx conducts a depth-first search for the specified element. If such an element
// is found a reference to it is returned.
func
NSFindOneCtx
(
ctx
NSContext
,
el
*
etree
.
Element
,
namespace
,
tag
string
)
(
*
etree
.
Element
,
error
)
{
var
found
*
etree
.
Element
var
found
*
etree
.
Element
err
:=
NSFindIterate
(
el
,
namespace
,
tag
,
func
(
el
*
etree
.
Element
)
error
{
err
:=
NSFindIterate
Ctx
(
ctx
,
el
,
namespace
,
tag
,
func
(
ctx
NSContext
,
el
*
etree
.
Element
)
error
{
found
=
el
found
=
el
return
ErrTraversalHalted
return
ErrTraversalHalted
})
})
...
@@ -250,3 +308,21 @@ func NSFindOne(el *etree.Element, namespace, tag string) (*etree.Element, error)
...
@@ -250,3 +308,21 @@ func NSFindOne(el *etree.Element, namespace, tag string) (*etree.Element, error)
return
found
,
nil
return
found
,
nil
}
}
// NSBuildParentContext recurses upward from an element in order to build an NSContext
// for its immediate parent. If the element has no parent DefaultNSContext
// is returned.
func
NSBuildParentContext
(
el
*
etree
.
Element
)
(
NSContext
,
error
)
{
parent
:=
el
.
Parent
()
if
parent
==
nil
{
return
DefaultNSContext
,
nil
}
ctx
,
err
:=
NSBuildParentContext
(
parent
)
if
err
!=
nil
{
return
ctx
,
err
}
return
ctx
.
SubContext
(
parent
)
}
vendor/github.com/russellhaering/goxmldsig/etreeutils/sort.go
View file @
4b457d8c
...
@@ -2,6 +2,8 @@ package etreeutils
...
@@ -2,6 +2,8 @@ package etreeutils
import
"github.com/beevik/etree"
import
"github.com/beevik/etree"
// SortedAttrs provides sorting capabilities, compatible with XML C14N, on top
// of an []etree.Attr
type
SortedAttrs
[]
etree
.
Attr
type
SortedAttrs
[]
etree
.
Attr
func
(
a
SortedAttrs
)
Len
()
int
{
func
(
a
SortedAttrs
)
Len
()
int
{
...
@@ -13,17 +15,23 @@ func (a SortedAttrs) Swap(i, j int) {
...
@@ -13,17 +15,23 @@ func (a SortedAttrs) Swap(i, j int) {
}
}
func
(
a
SortedAttrs
)
Less
(
i
,
j
int
)
bool
{
func
(
a
SortedAttrs
)
Less
(
i
,
j
int
)
bool
{
// As I understand it: any "xmlns" attribute should come first, followed by any
// This is the best reference I've found on sort order:
// any "xmlns:prefix" attributes, presumably ordered by prefix. Lastly any other
// http://dst.lbl.gov/~ksb/Scratch/XMLC14N.html
// attributes in lexicographical order.
if
a
[
i
]
.
Space
==
defaultPrefix
&&
a
[
i
]
.
Key
==
xmlnsPrefix
{
return
true
}
// If attr j is a default namespace declaration, attr i may
// not be strictly "less" than it.
if
a
[
j
]
.
Space
==
defaultPrefix
&&
a
[
j
]
.
Key
==
xmlnsPrefix
{
if
a
[
j
]
.
Space
==
defaultPrefix
&&
a
[
j
]
.
Key
==
xmlnsPrefix
{
return
false
return
false
}
}
// Otherwise, if attr i is a default namespace declaration, it
// must be less than anything else.
if
a
[
i
]
.
Space
==
defaultPrefix
&&
a
[
i
]
.
Key
==
xmlnsPrefix
{
return
true
}
// Next, namespace prefix declarations, sorted by prefix, come before
// anythign else.
if
a
[
i
]
.
Space
==
xmlnsPrefix
{
if
a
[
i
]
.
Space
==
xmlnsPrefix
{
if
a
[
j
]
.
Space
==
xmlnsPrefix
{
if
a
[
j
]
.
Space
==
xmlnsPrefix
{
return
a
[
i
]
.
Key
<
a
[
j
]
.
Key
return
a
[
i
]
.
Key
<
a
[
j
]
.
Key
...
@@ -35,6 +43,21 @@ func (a SortedAttrs) Less(i, j int) bool {
...
@@ -35,6 +43,21 @@ func (a SortedAttrs) Less(i, j int) bool {
return
false
return
false
}
}
// Then come unprefixed attributes, sorted by key.
if
a
[
i
]
.
Space
==
defaultPrefix
{
if
a
[
j
]
.
Space
==
defaultPrefix
{
return
a
[
i
]
.
Key
<
a
[
j
]
.
Key
}
return
true
}
if
a
[
j
]
.
Space
==
defaultPrefix
{
return
false
}
// Wow. We're still going. Finally, attributes in the same namespace should be
// sorted by key. Attributes in different namespaces should be sorted by the
// actual namespace (_not_ the prefix). For now just use the prefix.
if
a
[
i
]
.
Space
==
a
[
j
]
.
Space
{
if
a
[
i
]
.
Space
==
a
[
j
]
.
Space
{
return
a
[
i
]
.
Key
<
a
[
j
]
.
Key
return
a
[
i
]
.
Key
<
a
[
j
]
.
Key
}
}
...
...
vendor/github.com/russellhaering/goxmldsig/etreeutils/unmarshal.go
0 → 100644
View file @
4b457d8c
package
etreeutils
import
(
"encoding/xml"
"github.com/beevik/etree"
)
// NSUnmarshalElement unmarshals the passed etree Element into the value pointed to by
// v using encoding/xml in the context of the passed NSContext. If v implements
// ElementKeeper, SetUnderlyingElement will be called on v with a reference to el.
func
NSUnmarshalElement
(
ctx
NSContext
,
el
*
etree
.
Element
,
v
interface
{})
error
{
detatched
,
err
:=
NSDetatch
(
ctx
,
el
)
if
err
!=
nil
{
return
err
}
doc
:=
etree
.
NewDocument
()
doc
.
AddChild
(
detatched
)
data
,
err
:=
doc
.
WriteToBytes
()
if
err
!=
nil
{
return
err
}
err
=
xml
.
Unmarshal
(
data
,
v
)
if
err
!=
nil
{
return
err
}
switch
v
:=
v
.
(
type
)
{
case
ElementKeeper
:
v
.
SetUnderlyingElement
(
el
)
}
return
nil
}
// ElementKeeper should be implemented by types which will be passed to
// UnmarshalElement, but wish to keep a reference
type
ElementKeeper
interface
{
SetUnderlyingElement
(
*
etree
.
Element
)
UnderlyingElement
()
*
etree
.
Element
}
vendor/github.com/russellhaering/goxmldsig/sign.go
View file @
4b457d8c
...
@@ -11,6 +11,7 @@ import (
...
@@ -11,6 +11,7 @@ import (
"fmt"
"fmt"
"github.com/beevik/etree"
"github.com/beevik/etree"
"github.com/russellhaering/goxmldsig/etreeutils"
)
)
type
SigningContext
struct
{
type
SigningContext
struct
{
...
@@ -133,15 +134,39 @@ func (ctx *SigningContext) constructSignature(el *etree.Element, enveloped bool)
...
@@ -133,15 +134,39 @@ func (ctx *SigningContext) constructSignature(el *etree.Element, enveloped bool)
}
}
sig
.
CreateAttr
(
xmlns
,
Namespace
)
sig
.
CreateAttr
(
xmlns
,
Namespace
)
sig
.
AddChild
(
signedInfo
)
sig
.
Child
=
append
(
sig
.
Child
,
signedInfo
)
// When using xml-c14n11 (ie, non-exclusive canonicalization) the canonical form
// of the SignedInfo must declare all namespaces that are in scope at it's final
// enveloped location in the document. In order to do that, we're going to construct
// a series of cascading NSContexts to capture namespace declarations:
// Must propagate down the attributes to the 'SignedInfo' before digesting
// First get the context surrounding the element we are signing.
for
_
,
attr
:=
range
sig
.
Attr
{
rootNSCtx
,
err
:=
etreeutils
.
NSBuildParentContext
(
el
)
signedInfo
.
CreateAttr
(
attr
.
Space
+
":"
+
attr
.
Key
,
attr
.
Value
)
if
err
!=
nil
{
return
nil
,
err
}
// Then capture any declarations on the element itself.
elNSCtx
,
err
:=
rootNSCtx
.
SubContext
(
el
)
if
err
!=
nil
{
return
nil
,
err
}
// Followed by declarations on the Signature (which we just added above)
sigNSCtx
,
err
:=
elNSCtx
.
SubContext
(
sig
)
if
err
!=
nil
{
return
nil
,
err
}
// Finally detatch the SignedInfo in order to capture all of the namespace
// declarations in the scope we've constructed.
detatchedSignedInfo
,
err
:=
etreeutils
.
NSDetatch
(
sigNSCtx
,
signedInfo
)
if
err
!=
nil
{
return
nil
,
err
}
}
digest
,
err
:=
ctx
.
digest
(
s
ignedInfo
)
digest
,
err
:=
ctx
.
digest
(
detatchedS
ignedInfo
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
...
vendor/github.com/russellhaering/goxmldsig/types/signature.go
0 → 100644
View file @
4b457d8c
package
types
import
(
"encoding/xml"
"github.com/beevik/etree"
)
type
InclusiveNamespaces
struct
{
XMLName
xml
.
Name
`xml:"http://www.w3.org/2001/10/xml-exc-c14n# InclusiveNamespaces"`
PrefixList
string
`xml:"PrefixList,attr"`
}
type
Transform
struct
{
XMLName
xml
.
Name
`xml:"http://www.w3.org/2000/09/xmldsig# Transform"`
Algorithm
string
`xml:"Algorithm,attr"`
InclusiveNamespaces
*
InclusiveNamespaces
`xml:"InclusiveNamespaces"`
}
type
Transforms
struct
{
XMLName
xml
.
Name
`xml:"http://www.w3.org/2000/09/xmldsig# Transforms"`
Transforms
[]
Transform
`xml:"Transform"`
}
type
DigestMethod
struct
{
XMLName
xml
.
Name
`xml:"http://www.w3.org/2000/09/xmldsig# DigestMethod"`
Algorithm
string
`xml:"Algorithm,attr"`
}
type
Reference
struct
{
XMLName
xml
.
Name
`xml:"http://www.w3.org/2000/09/xmldsig# Reference"`
URI
string
`xml:"URI,attr"`
DigestValue
string
`xml:"DigestValue"`
DigestAlgo
DigestMethod
`xml:"DigestMethod"`
Transforms
Transforms
`xml:"Transforms"`
}
type
CanonicalizationMethod
struct
{
XMLName
xml
.
Name
`xml:"http://www.w3.org/2000/09/xmldsig# CanonicalizationMethod"`
Algorithm
string
`xml:"Algorithm,attr"`
}
type
SignatureMethod
struct
{
XMLName
xml
.
Name
`xml:"http://www.w3.org/2000/09/xmldsig# SignatureMethod"`
Algorithm
string
`xml:"Algorithm,attr"`
}
type
SignedInfo
struct
{
XMLName
xml
.
Name
`xml:"http://www.w3.org/2000/09/xmldsig# SignedInfo"`
CanonicalizationMethod
CanonicalizationMethod
`xml:"CanonicalizationMethod"`
SignatureMethod
SignatureMethod
`xml:"SignatureMethod"`
References
[]
Reference
`xml:"Reference"`
}
type
SignatureValue
struct
{
XMLName
xml
.
Name
`xml:"http://www.w3.org/2000/09/xmldsig# SignatureValue"`
Data
string
`xml:",chardata"`
}
type
KeyInfo
struct
{
XMLName
xml
.
Name
`xml:"http://www.w3.org/2000/09/xmldsig# KeyInfo"`
X509Data
X509Data
`xml:"X509Data"`
}
type
X509Data
struct
{
XMLName
xml
.
Name
`xml:"http://www.w3.org/2000/09/xmldsig# X509Data"`
X509Certificate
X509Certificate
`xml:"X509Certificate"`
}
type
X509Certificate
struct
{
XMLName
xml
.
Name
`xml:"http://www.w3.org/2000/09/xmldsig# X509Certificate"`
Data
string
`xml:",chardata"`
}
type
Signature
struct
{
XMLName
xml
.
Name
`xml:"http://www.w3.org/2000/09/xmldsig# Signature"`
SignedInfo
*
SignedInfo
`xml:"SignedInfo"`
SignatureValue
*
SignatureValue
`xml:"SignatureValue"`
KeyInfo
*
KeyInfo
`xml:"KeyInfo"`
el
*
etree
.
Element
}
// SetUnderlyingElement will be called with a reference to the Element this Signature
// was unmarshaled from.
func
(
s
*
Signature
)
SetUnderlyingElement
(
el
*
etree
.
Element
)
{
s
.
el
=
el
}
// UnderlyingElement returns a reference to the Element this signature was unmarshaled
// from, where applicable.
func
(
s
*
Signature
)
UnderlyingElement
()
*
etree
.
Element
{
return
s
.
el
}
vendor/github.com/russellhaering/goxmldsig/validate.go
View file @
4b457d8c
...
@@ -11,6 +11,7 @@ import (
...
@@ -11,6 +11,7 @@ import (
"github.com/beevik/etree"
"github.com/beevik/etree"
"github.com/russellhaering/goxmldsig/etreeutils"
"github.com/russellhaering/goxmldsig/etreeutils"
"github.com/russellhaering/goxmldsig/types"
)
)
var
uriRegexp
=
regexp
.
MustCompile
(
"^#[a-zA-Z_][
\\
w.-]*$"
)
var
uriRegexp
=
regexp
.
MustCompile
(
"^#[a-zA-Z_][
\\
w.-]*$"
)
...
@@ -82,7 +83,12 @@ func recursivelyRemoveElement(tree, el *etree.Element) bool {
...
@@ -82,7 +83,12 @@ func recursivelyRemoveElement(tree, el *etree.Element) bool {
// instead return a copy. Unfortunately copying the tree makes it difficult to
// instead return a copy. Unfortunately copying the tree makes it difficult to
// correctly locate the signature. I'm opting, for now, to simply mutate the root
// correctly locate the signature. I'm opting, for now, to simply mutate the root
// parameter.
// parameter.
func
(
ctx
*
ValidationContext
)
transform
(
root
,
sig
*
etree
.
Element
,
transforms
[]
*
etree
.
Element
)
(
*
etree
.
Element
,
Canonicalizer
,
error
)
{
func
(
ctx
*
ValidationContext
)
transform
(
el
*
etree
.
Element
,
sig
*
types
.
Signature
,
ref
*
types
.
Reference
)
(
*
etree
.
Element
,
Canonicalizer
,
error
)
{
transforms
:=
ref
.
Transforms
.
Transforms
if
len
(
transforms
)
!=
2
{
if
len
(
transforms
)
!=
2
{
return
nil
,
nil
,
errors
.
New
(
"Expected Enveloped and C14N transforms"
)
return
nil
,
nil
,
errors
.
New
(
"Expected Enveloped and C14N transforms"
)
}
}
...
@@ -90,25 +96,18 @@ func (ctx *ValidationContext) transform(root, sig *etree.Element, transforms []*
...
@@ -90,25 +96,18 @@ func (ctx *ValidationContext) transform(root, sig *etree.Element, transforms []*
var
canonicalizer
Canonicalizer
var
canonicalizer
Canonicalizer
for
_
,
transform
:=
range
transforms
{
for
_
,
transform
:=
range
transforms
{
algo
:=
transform
.
SelectAttr
(
AlgorithmAttr
)
algo
:=
transform
.
Algorithm
if
algo
==
nil
{
return
nil
,
nil
,
errors
.
New
(
"Missing Algorithm attribute"
)
}
switch
AlgorithmID
(
algo
.
Value
)
{
switch
AlgorithmID
(
algo
)
{
case
EnvelopedSignatureAltorithmId
:
case
EnvelopedSignatureAltorithmId
:
if
!
recursivelyRemoveElement
(
root
,
sig
)
{
if
!
recursivelyRemoveElement
(
el
,
sig
.
UnderlyingElement
()
)
{
return
nil
,
nil
,
errors
.
New
(
"Error applying canonicalization transform: Signature not found"
)
return
nil
,
nil
,
errors
.
New
(
"Error applying canonicalization transform: Signature not found"
)
}
}
case
CanonicalXML10ExclusiveAlgorithmId
:
case
CanonicalXML10ExclusiveAlgorithmId
:
var
prefixList
string
var
prefixList
string
ins
:=
transform
.
FindElement
(
childPath
(
""
,
InclusiveNamespacesTag
))
if
transform
.
InclusiveNamespaces
!=
nil
{
if
ins
!=
nil
{
prefixList
=
transform
.
InclusiveNamespaces
.
PrefixList
prefixListEl
:=
ins
.
SelectAttr
(
PrefixListAttr
)
if
prefixListEl
!=
nil
{
prefixList
=
prefixListEl
.
Value
}
}
}
canonicalizer
=
MakeC14N10ExclusiveCanonicalizerWithPrefixList
(
prefixList
)
canonicalizer
=
MakeC14N10ExclusiveCanonicalizerWithPrefixList
(
prefixList
)
...
@@ -117,7 +116,7 @@ func (ctx *ValidationContext) transform(root, sig *etree.Element, transforms []*
...
@@ -117,7 +116,7 @@ func (ctx *ValidationContext) transform(root, sig *etree.Element, transforms []*
canonicalizer
=
MakeC14N11Canonicalizer
()
canonicalizer
=
MakeC14N11Canonicalizer
()
default
:
default
:
return
nil
,
nil
,
errors
.
New
(
"Unknown Transform Algorithm: "
+
algo
.
Value
)
return
nil
,
nil
,
errors
.
New
(
"Unknown Transform Algorithm: "
+
algo
)
}
}
}
}
...
@@ -125,7 +124,7 @@ func (ctx *ValidationContext) transform(root, sig *etree.Element, transforms []*
...
@@ -125,7 +124,7 @@ func (ctx *ValidationContext) transform(root, sig *etree.Element, transforms []*
return
nil
,
nil
,
errors
.
New
(
"Expected canonicalization transform"
)
return
nil
,
nil
,
errors
.
New
(
"Expected canonicalization transform"
)
}
}
return
root
,
canonicalizer
,
nil
return
el
,
canonicalizer
,
nil
}
}
func
(
ctx
*
ValidationContext
)
digest
(
el
*
etree
.
Element
,
digestAlgorithmId
string
,
canonicalizer
Canonicalizer
)
([]
byte
,
error
)
{
func
(
ctx
*
ValidationContext
)
digest
(
el
*
etree
.
Element
,
digestAlgorithmId
string
,
canonicalizer
Canonicalizer
)
([]
byte
,
error
)
{
...
@@ -148,19 +147,16 @@ func (ctx *ValidationContext) digest(el *etree.Element, digestAlgorithmId string
...
@@ -148,19 +147,16 @@ func (ctx *ValidationContext) digest(el *etree.Element, digestAlgorithmId string
return
hash
.
Sum
(
nil
),
nil
return
hash
.
Sum
(
nil
),
nil
}
}
func
(
ctx
*
ValidationContext
)
verifySignedInfo
(
signatureElement
*
etree
.
Element
,
canonicalizer
Canonicalizer
,
signatureMethodId
string
,
cert
*
x509
.
Certificate
,
sig
[]
byte
)
error
{
func
(
ctx
*
ValidationContext
)
verifySignedInfo
(
sig
*
types
.
Signature
,
canonicalizer
Canonicalizer
,
signatureMethodId
string
,
cert
*
x509
.
Certificate
,
decodedSignature
[]
byte
)
error
{
signatureElement
:=
sig
.
UnderlyingElement
()
signedInfo
:=
signatureElement
.
FindElement
(
childPath
(
signatureElement
.
Space
,
SignedInfoTag
))
signedInfo
:=
signatureElement
.
FindElement
(
childPath
(
signatureElement
.
Space
,
SignedInfoTag
))
if
signedInfo
==
nil
{
if
signedInfo
==
nil
{
return
errors
.
New
(
"Missing SignedInfo"
)
return
errors
.
New
(
"Missing SignedInfo"
)
}
}
// Any attributes from the 'Signature' element must be pushed down into the 'SignedInfo' element before it is canonicalized
for
_
,
attr
:=
range
signatureElement
.
Attr
{
signedInfo
.
CreateAttr
(
attr
.
Space
+
":"
+
attr
.
Key
,
attr
.
Value
)
}
// Canonicalize the xml
// Canonicalize the xml
canonical
,
err
:=
canonical
izer
.
Canonic
alize
(
signedInfo
)
canonical
,
err
:=
canonical
Seri
alize
(
signedInfo
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -184,7 +180,7 @@ func (ctx *ValidationContext) verifySignedInfo(signatureElement *etree.Element,
...
@@ -184,7 +180,7 @@ func (ctx *ValidationContext) verifySignedInfo(signatureElement *etree.Element,
}
}
// Verify that the private key matching the public key from the cert was what was used to sign the 'SignedInfo' and produce the 'SignatureValue'
// Verify that the private key matching the public key from the cert was what was used to sign the 'SignedInfo' and produce the 'SignatureValue'
err
=
rsa
.
VerifyPKCS1v15
(
pubKey
,
signatureAlgorithm
,
hashed
[
:
],
sig
)
err
=
rsa
.
VerifyPKCS1v15
(
pubKey
,
signatureAlgorithm
,
hashed
[
:
],
decodedSignature
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -192,65 +188,37 @@ func (ctx *ValidationContext) verifySignedInfo(signatureElement *etree.Element,
...
@@ -192,65 +188,37 @@ func (ctx *ValidationContext) verifySignedInfo(signatureElement *etree.Element,
return
nil
return
nil
}
}
func
(
ctx
*
ValidationContext
)
validateSignature
(
el
,
sig
*
etree
.
Element
,
cert
*
x509
.
Certificate
)
(
*
etree
.
Element
,
error
)
{
func
(
ctx
*
ValidationContext
)
validateSignature
(
el
*
etree
.
Element
,
sig
*
types
.
Signature
,
cert
*
x509
.
Certificate
)
(
*
etree
.
Element
,
error
)
{
// Get the 'SignedInfo' element
idAttr
:=
el
.
SelectAttr
(
DefaultIdAttr
)
signedInfo
:=
sig
.
FindElement
(
childPath
(
sig
.
Space
,
SignedInfoTag
))
if
idAttr
==
nil
||
idAttr
.
Value
==
""
{
if
signedInfo
==
nil
{
return
nil
,
errors
.
New
(
"Missing ID attribute"
)
return
nil
,
errors
.
New
(
"Missing SignedInfo"
)
}
reference
:=
signedInfo
.
FindElement
(
childPath
(
sig
.
Space
,
ReferenceTag
))
if
reference
==
nil
{
return
nil
,
errors
.
New
(
"Missing Reference"
)
}
}
transforms
:=
reference
.
FindElement
(
childPath
(
sig
.
Space
,
TransformsTag
))
var
ref
*
types
.
Reference
if
transforms
==
nil
{
return
nil
,
errors
.
New
(
"Missing Transforms"
)
}
uri
:=
reference
.
SelectAttr
(
"URI"
)
// Find the first reference which references the top-level element
if
uri
==
nil
{
for
_
,
_ref
:=
range
sig
.
SignedInfo
.
References
{
// TODO(russell_h): It is permissible to leave this out. We should be
if
_ref
.
URI
==
""
||
_ref
.
URI
[
1
:
]
==
idAttr
.
Value
{
// able to fall back to finding the referenced element some other way.
ref
=
&
_ref
return
nil
,
errors
.
New
(
"Reference is missing URI attribute"
)
}
}
// Get the element referenced in the 'SignedInfo'
referencedElement
:=
el
.
FindElement
(
fmt
.
Sprintf
(
"//[@%s='%s']"
,
ctx
.
IdAttribute
,
uri
.
Value
[
1
:
]))
if
referencedElement
==
nil
{
return
nil
,
errors
.
New
(
"Unable to find referenced element: "
+
uri
.
Value
)
}
}
// Perform all transformations listed in the 'SignedInfo'
// Perform all transformations listed in the 'SignedInfo'
// Basically, this means removing the 'SignedInfo'
// Basically, this means removing the 'SignedInfo'
transformed
,
canonicalizer
,
err
:=
ctx
.
transform
(
referencedElement
,
sig
,
transforms
.
ChildElements
()
)
transformed
,
canonicalizer
,
err
:=
ctx
.
transform
(
el
,
sig
,
ref
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
digestMethod
:=
reference
.
FindElement
(
childPath
(
sig
.
Space
,
DigestMethodTag
))
digestAlgorithm
:=
ref
.
DigestAlgo
.
Algorithm
if
digestMethod
==
nil
{
return
nil
,
errors
.
New
(
"Missing DigestMethod"
)
}
digestValue
:=
reference
.
FindElement
(
childPath
(
sig
.
Space
,
DigestValueTag
))
if
digestValue
==
nil
{
return
nil
,
errors
.
New
(
"Missing DigestValue"
)
}
digestAlgorithmAttr
:=
digestMethod
.
SelectAttr
(
AlgorithmAttr
)
if
digestAlgorithmAttr
==
nil
{
return
nil
,
errors
.
New
(
"Missing DigestMethod Algorithm attribute"
)
}
// Digest the transformed XML and compare it to the 'DigestValue' from the 'SignedInfo'
// Digest the transformed XML and compare it to the 'DigestValue' from the 'SignedInfo'
digest
,
err
:=
ctx
.
digest
(
transformed
,
digestAlgorithm
Attr
.
Value
,
canonicalizer
)
digest
,
err
:=
ctx
.
digest
(
transformed
,
digestAlgorithm
,
canonicalizer
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
decodedDigestValue
,
err
:=
base64
.
StdEncoding
.
DecodeString
(
digestValue
.
Text
()
)
decodedDigestValue
,
err
:=
base64
.
StdEncoding
.
DecodeString
(
ref
.
DigestValue
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -259,30 +227,15 @@ func (ctx *ValidationContext) validateSignature(el, sig *etree.Element, cert *x5
...
@@ -259,30 +227,15 @@ func (ctx *ValidationContext) validateSignature(el, sig *etree.Element, cert *x5
return
nil
,
errors
.
New
(
"Signature could not be verified"
)
return
nil
,
errors
.
New
(
"Signature could not be verified"
)
}
}
//Verify the signed info
signatureMethod
:=
signedInfo
.
FindElement
(
childPath
(
sig
.
Space
,
SignatureMethodTag
))
if
signatureMethod
==
nil
{
return
nil
,
errors
.
New
(
"Missing SignatureMethod"
)
}
signatureMethodAlgorithmAttr
:=
signatureMethod
.
SelectAttr
(
AlgorithmAttr
)
if
digestAlgorithmAttr
==
nil
{
return
nil
,
errors
.
New
(
"Missing SignatureMethod Algorithm attribute"
)
}
// Decode the 'SignatureValue' so we can compare against it
// Decode the 'SignatureValue' so we can compare against it
signatureValue
:=
sig
.
FindElement
(
childPath
(
sig
.
Space
,
SignatureValueTag
))
decodedSignature
,
err
:=
base64
.
StdEncoding
.
DecodeString
(
sig
.
SignatureValue
.
Data
)
if
signatureValue
==
nil
{
return
nil
,
errors
.
New
(
"Missing SignatureValue"
)
}
decodedSignature
,
err
:=
base64
.
StdEncoding
.
DecodeString
(
signatureValue
.
Text
())
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
errors
.
New
(
"Could not decode signature"
)
return
nil
,
errors
.
New
(
"Could not decode signature"
)
}
}
// Actually verify the 'SignedInfo' was signed by a trusted source
// Actually verify the 'SignedInfo' was signed by a trusted source
err
=
ctx
.
verifySignedInfo
(
sig
,
canonicalizer
,
signatureMethodAlgorithmAttr
.
Value
,
cert
,
decodedSignature
)
signatureMethod
:=
sig
.
SignedInfo
.
SignatureMethod
.
Algorithm
err
=
ctx
.
verifySignedInfo
(
sig
,
canonicalizer
,
signatureMethod
,
cert
,
decodedSignature
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -300,38 +253,89 @@ func contains(roots []*x509.Certificate, cert *x509.Certificate) bool {
...
@@ -300,38 +253,89 @@ func contains(roots []*x509.Certificate, cert *x509.Certificate) bool {
}
}
// findSignature searches for a Signature element referencing the passed root element.
// findSignature searches for a Signature element referencing the passed root element.
func
(
ctx
*
ValidationContext
)
findSignature
(
el
*
etree
.
Element
)
(
*
etree
.
Element
,
error
)
{
func
(
ctx
*
ValidationContext
)
findSignature
(
el
*
etree
.
Element
)
(
*
types
.
Signature
,
error
)
{
idAttr
:=
el
.
SelectAttr
(
DefaultIdAttr
)
idAttr
:=
el
.
SelectAttr
(
DefaultIdAttr
)
if
idAttr
==
nil
||
idAttr
.
Value
==
""
{
if
idAttr
==
nil
||
idAttr
.
Value
==
""
{
return
nil
,
errors
.
New
(
"Missing ID attribute"
)
return
nil
,
errors
.
New
(
"Missing ID attribute"
)
}
}
var
sig
natureElement
*
etree
.
Element
var
sig
*
types
.
Signature
err
:=
etreeutils
.
NSFindIterate
(
el
,
Namespace
,
SignatureTag
,
func
(
sig
*
etree
.
Element
)
error
{
// Traverse the tree looking for a Signature element
signedInfo
:=
sig
.
FindElement
(
childPath
(
sig
.
Space
,
SignedInfoTag
))
err
:=
etreeutils
.
NSFindIterate
(
el
,
Namespace
,
SignatureTag
,
func
(
ctx
etreeutils
.
NSContext
,
el
*
etree
.
Element
)
error
{
if
signedInfo
==
nil
{
return
errors
.
New
(
"Missing SignedInfo"
)
found
:=
false
err
:=
etreeutils
.
NSFindIterateCtx
(
ctx
,
el
,
Namespace
,
SignedInfoTag
,
func
(
ctx
etreeutils
.
NSContext
,
signedInfo
*
etree
.
Element
)
error
{
// Ignore any SignedInfo that isn't an immediate descendent of Signature.
if
signedInfo
.
Parent
()
!=
el
{
return
nil
}
detachedSignedInfo
,
err
:=
etreeutils
.
NSDetatch
(
ctx
,
signedInfo
)
if
err
!=
nil
{
return
err
}
c14NMethod
:=
detachedSignedInfo
.
FindElement
(
childPath
(
detachedSignedInfo
.
Space
,
CanonicalizationMethodTag
))
if
c14NMethod
==
nil
{
return
errors
.
New
(
"missing CanonicalizationMethod on Signature"
)
}
c14NAlgorithm
:=
c14NMethod
.
SelectAttrValue
(
AlgorithmAttr
,
""
)
var
canonicalSignedInfo
*
etree
.
Element
switch
AlgorithmID
(
c14NAlgorithm
)
{
case
CanonicalXML10ExclusiveAlgorithmId
:
err
:=
etreeutils
.
TransformExcC14n
(
detachedSignedInfo
,
""
)
if
err
!=
nil
{
return
err
}
// NOTE: TransformExcC14n transforms the element in-place,
// while canonicalPrep isn't meant to. Once we standardize
// this behavior we can drop this, as well as the adding and
// removing of elements below.
canonicalSignedInfo
=
detachedSignedInfo
case
CanonicalXML11AlgorithmId
:
canonicalSignedInfo
=
canonicalPrep
(
detachedSignedInfo
,
map
[
string
]
struct
{}{})
default
:
return
fmt
.
Errorf
(
"invalid CanonicalizationMethod on Signature: %s"
,
c14NAlgorithm
)
}
}
referenceElement
:=
signedInfo
.
FindElement
(
childPath
(
sig
.
Space
,
ReferenceTag
))
el
.
RemoveChild
(
signedInfo
)
if
referenceElement
==
nil
{
el
.
AddChild
(
canonicalSignedInfo
)
return
errors
.
New
(
"Missing Reference Element"
)
found
=
true
return
etreeutils
.
ErrTraversalHalted
})
if
err
!=
nil
{
return
err
}
}
uriAttr
:=
referenceElement
.
SelectAttr
(
URIAttr
)
if
!
found
{
if
uriAttr
==
nil
||
uriAttr
.
Value
==
""
{
return
errors
.
New
(
"Missing SignedInfo"
)
return
errors
.
New
(
"Missing URI attribute"
)
}
}
if
!
uriRegexp
.
MatchString
(
uriAttr
.
Value
)
{
// Unmarshal the signature into a structured Signature type
return
errors
.
New
(
"Invalid URI: "
+
uriAttr
.
Value
)
_sig
:=
&
types
.
Signature
{}
err
=
etreeutils
.
NSUnmarshalElement
(
ctx
,
el
,
_sig
)
if
err
!=
nil
{
return
err
}
}
if
uriAttr
.
Value
[
1
:
]
==
idAttr
.
Value
{
// Traverse references in the signature to determine whether it has at least
signatureElement
=
sig
// one reference to the top level element. If so, conclude the search.
for
_
,
ref
:=
range
_sig
.
SignedInfo
.
References
{
if
ref
.
URI
==
""
||
ref
.
URI
[
1
:
]
==
idAttr
.
Value
{
sig
=
_sig
return
etreeutils
.
ErrTraversalHalted
return
etreeutils
.
ErrTraversalHalted
}
}
}
return
nil
return
nil
})
})
...
@@ -340,14 +344,14 @@ func (ctx *ValidationContext) findSignature(el *etree.Element) (*etree.Element,
...
@@ -340,14 +344,14 @@ func (ctx *ValidationContext) findSignature(el *etree.Element) (*etree.Element,
return
nil
,
err
return
nil
,
err
}
}
if
sig
natureElement
==
nil
{
if
sig
==
nil
{
return
nil
,
ErrMissingSignature
return
nil
,
ErrMissingSignature
}
}
return
sig
natureElement
,
nil
return
sig
,
nil
}
}
func
(
ctx
*
ValidationContext
)
verifyCertificate
(
sig
natureElement
*
etree
.
Element
)
(
*
x509
.
Certificate
,
error
)
{
func
(
ctx
*
ValidationContext
)
verifyCertificate
(
sig
*
types
.
Signature
)
(
*
x509
.
Certificate
,
error
)
{
now
:=
ctx
.
Clock
.
Now
()
now
:=
ctx
.
Clock
.
Now
()
roots
,
err
:=
ctx
.
CertificateStore
.
Certificates
()
roots
,
err
:=
ctx
.
CertificateStore
.
Certificates
()
...
@@ -357,17 +361,13 @@ func (ctx *ValidationContext) verifyCertificate(signatureElement *etree.Element)
...
@@ -357,17 +361,13 @@ func (ctx *ValidationContext) verifyCertificate(signatureElement *etree.Element)
var
cert
*
x509
.
Certificate
var
cert
*
x509
.
Certificate
// Get the x509 element from the signature
if
sig
.
KeyInfo
!=
nil
{
x509Element
:=
signatureElement
.
FindElement
(
"//"
+
childPath
(
signatureElement
.
Space
,
X509CertificateTag
))
// If the Signature includes KeyInfo, extract the certificate from there
if
x509Element
==
nil
{
if
sig
.
KeyInfo
.
X509Data
.
X509Certificate
.
Data
==
""
{
// Use root certificate if there is only one and it is not contained in signatureElement
return
nil
,
errors
.
New
(
"missing X509Certificate within KeyInfo"
)
if
len
(
roots
)
==
1
{
cert
=
roots
[
0
]
}
else
{
return
nil
,
errors
.
New
(
"Missing x509 Element"
)
}
}
}
else
{
certData
,
err
:=
base64
.
StdEncoding
.
DecodeString
(
x509Element
.
Text
()
)
certData
,
err
:=
base64
.
StdEncoding
.
DecodeString
(
sig
.
KeyInfo
.
X509Data
.
X509Certificate
.
Data
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
errors
.
New
(
"Failed to parse certificate"
)
return
nil
,
errors
.
New
(
"Failed to parse certificate"
)
}
}
...
@@ -376,6 +376,13 @@ func (ctx *ValidationContext) verifyCertificate(signatureElement *etree.Element)
...
@@ -376,6 +376,13 @@ func (ctx *ValidationContext) verifyCertificate(signatureElement *etree.Element)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
}
else
{
// If the Signature doesn't have KeyInfo, Use the root certificate if there is only one
if
len
(
roots
)
==
1
{
cert
=
roots
[
0
]
}
else
{
return
nil
,
errors
.
New
(
"Missing x509 Element"
)
}
}
}
// Verify that the certificate is one we trust
// Verify that the certificate is one we trust
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment