1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
#!/bin/sh -
# $Id$
# Demo of how one could use the xmlsec package to sign and verify XML
# messages. On FreeBSD, the xmlsec 1.x command line program is called
# "xmlsec1" to distinuish it from the old xmlsec 0.x program, which
# had a somewhat different command line syntax. YMMV.
#
# Basic idea of the demo is to create a four level deep cert chain,
# use that to sign an XML document, then demonstrate that it verifies.
# Subsequent discussion on the mailing list concluded that xmlsec (the
# protocol, not just this particular implementation) is hopelessly
# broken and that we should just use CMS (aka PKCS#7 ng). Done.
set -xe
: ${input=input.xml} ${unsigned=unsigned.xml} ${signed=signed.xml}
: ${alice=alice} ${bob=bob} ${carol=carol} ${dave=dave}
: ${xmlsec=xmlsec1}
# Some input with which to work. Feel free to supply your own instead.
test -r $input || cat >$input <<'EOF'
<reference anchor="RFC3779">
<front>
<title>X.509 Extensions for IP Addresses and AS Identifiers</title>
<author fullname="C. Lynn" initials="C." surname="Lynn">
<organization/>
</author>
<author fullname="S. Kent" initials="S." surname="Kent">
<organization/>
</author>
<author fullname="K. Seo" initials="K." surname="Seo">
<organization/>
</author>
<date month="June" year="2004"/>
<keyword>allocation</keyword>
<keyword>atrribute certificate</keyword>
<keyword>authorization</keyword>
<keyword>autonomous system number authorization</keyword>
<keyword>certificate</keyword>
<keyword>delegation</keyword>
<keyword>internet registry</keyword>
<keyword>ip address authorization</keyword>
<keyword>public key infrastructure</keyword>
<keyword>right-to-use</keyword>
<keyword>secure allocation </keyword>
<abstract>
<t>This document defines two X.509 v3 certificate extensions. The
first binds a list of IP address blocks, or prefixes, to the
subject of a certificate. The second binds a list of autonomous
system identifiers to the subject of a certificate. These
extensions may be used to convey the authorization of the
subject to use the IP addresses and autonomous system
identifiers contained in the extensions. [STANDARDS TRACK]
</t>
</abstract>
</front>
<seriesInfo name="RFC" value="3779"/>
<format type="TXT" octets="60732" target="http://www.rfc-editor.org/rfc/rfc3779.txt"/>
<!-- current-status PROPOSED STANDARD -->
<!-- publication-status PROPOSED STANDARD -->
</reference>
EOF
# Set up a simple chain of certs.
for i in $alice $bob $carol $dave
do
test -r $i.cnf || cat >$i.cnf <<EOF
[ req ]
distinguished_name = req_dn
x509_extensions = req_x509_ext
prompt = no
default_md = sha1
[ req_dn ]
CN = Test Certificate $i
[ req_x509_ext ]
basicConstraints = CA:true
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
EOF
test -r $i.key -a -r $i.req ||
openssl req -new -newkey rsa:2048 -nodes -keyout $i.key -out $i.req -config $i.cnf
done
test -r $alice.cer || openssl x509 -req -in $alice.req -out $alice.cer -extfile $alice.cnf -extensions req_x509_ext -signkey $alice.key
test -r $bob.cer || openssl x509 -req -in $bob.req -out $bob.cer -extfile $bob.cnf -extensions req_x509_ext -CA $alice.cer -CAkey $alice.key -CAcreateserial
test -r $carol.cer || openssl x509 -req -in $carol.req -out $carol.cer -extfile $carol.cnf -extensions req_x509_ext -CA $bob.cer -CAkey $bob.key -CAcreateserial
test -r $dave.cer || openssl x509 -req -in $dave.req -out $dave.cer -extfile $dave.cnf -extensions req_x509_ext -CA $carol.cer -CAkey $carol.key -CAcreateserial
# The xmlsec command line tool takes most of its instructions in the
# form of an XML template. XSLT was designed for this kind of work,
# so just use an XSL transform to wrap our input with the template.
#
# NB: The XML signature specification supports several different
# signing modes. In theory, which one of them I get is determined by
# the template. Documentation is a bit sparse, though, so I just went
# with the first halfway sane thing I found in the supplied examples.
test -r $unsigned ||
xsltproc --output $unsigned - $input <<'EOF'
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" encoding="us-ascii" indent="yes"/>
<xsl:template match="/">
<Envelope xmlns="urn:envelope">
<xsl:copy-of select="/"/>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference>
<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/>
</X509Data>
</KeyInfo>
</Signature>
</Envelope>
</xsl:template>
</xsl:stylesheet>
EOF
# Sign the template we generated. We sign with the bottommost key,
# and include the two bottommost certs in the signed document.
test -r $signed ||
$xmlsec sign --privkey-pem $dave.key,$dave.cer,$carol.cer --output $signed $unsigned
# Verify the signed message. We tell xmlsec to trust the root cert,
# and supply the second level cert as it's not in the signed message.
# This should be enough for xmlsec to verify the signature; removing
# any these should cause verification to fail (try it!).
$xmlsec verify --trusted-pem $alice.cer --untrusted-pem $bob.cer $signed
|