aboutsummaryrefslogtreecommitdiff
path: root/scripts/xmlsec-demo.sh
blob: dde26db38a985e343d093dde7d25a9c8c107147a (plain) (blame)
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