Change KeyInfo element from W3C XML Signature to ASCII

git-svn-id: file:///home/ksmith/gitmigration/svn/xmpp/trunk@2227 4b5297f7-1745-476d-ba37-a9c6900126ab
This commit is contained in:
Dirk Meyer 2008-09-08 19:29:23 +00:00
parent 2c12a385ad
commit 1d73af0bc1
1 changed files with 184 additions and 149 deletions

View File

@ -17,13 +17,30 @@
<spec>XMPP Core</spec>
<spec>XEP-0060</spec>
<spec>XEP-0163</spec>
<spec>W3C XML Signature</spec>
</dependencies>
<supersedes>None</supersedes>
<supersededby>None</supersededby>
<shortname>NOT YET ASSIGNED</shortname>
&ianpaterson;
&stpeter;
<author>
<firstname>Dirk</firstname>
<surname>Meyer</surname>
<email>dmeyer@tzi.de</email>
<jid>dmeyer@jabber.org</jid>
</author>
<revision>
<version>0.8</version>
<date>2008-09-08</date>
<initials>dm</initials>
<remark><p>Change KeyInfo element from W3C XML Signature to ASCII</p></remark>
</revision>
<revision>
<version>0.7</version>
<date>2008-03-03</date>
<initials>psa</initials>
<remark><p>Changed temporary namespace per XEP-0053 procedures; corrected several small errors in the text and examples.</p></remark>
</revision>
<revision>
<version>0.7</version>
<date>2008-03-03</date>
@ -72,10 +89,87 @@
<ul>
<li>Publishing public keys to a set of subscribers.</li>
<li>Querying another entity for its public keys.</li>
<li>Sign one key with another</li>
</ul>
<p>An entity MAY have multiple public keys with different formats, signatures, algorithms, strengths and expiry dates. Each client used by a user may use different keys.</p>
</section1>
<section1 topic='The KeyInfo Format' anchor='keyinfo'>
<p>This document does not use the 'http://www.w3.org/2000/09/xmldsig#' namespace as specified in &w3xmlsig; because it is too complicated and the complexity is not needed for this use case. The keyinfo element defined in the 'urn:xmpp:tmp:pubkey' namespace is based on the ASCII output most cryptographic libraries support. The keyinfo has three parts: a unique name, the public key data (optional) and signatures from other keys (optional). The name is the fingerprint of the public key. The unique name / fingerprint can be used to search for a key (see <link url='#pub'>Public Key Publication via PEP</link>) and MUST be written in lower case.</p>
<section2 topic='X.509 Certificate' anchor='x509'>
<p>Since X.509 has no standard fingerprint mechanisms, the SHA1 value in hex of the certificate is used as name. The public key data is the X.509 certificate in DER encoding. To be included in an XML stream the data is Base64 encoded.</p>
<example caption='X.509 Certificate'><![CDATA[
<keyinfo xmlns='urn:xmpp:tmp:pubkey'>
<name>428b1358a286430f628da23fb33ddaf6e474f5c5</name>
<x509cert>
MIICCTCCAXKgAwIBAgIJALhU0Id6xxwQMA0GCSqGSIb3DQEBBQUAMA4xDDAKBgNV
BAMTA2ZvbzAeFw0wNzEyMjgyMDA1MTRaFw0wODEyMjcyMDA1MTRaMA4xDDAKBgNV
BAMTA2ZvbzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0DPcfeJzKWLGE22p
RMINLKr+CxqozF14DqkXkLUwGzTqYRi49yK6aebZ9ssFspTTjqa2uNpw1U32748t
qU6bpACWHbcC+eZ/hm5KymXBhL3Vjfb/dW0xrtxjI9JRFgrgWAyxndlNZUpN2s3D
hKDfVgpPSx/Zp8d/ubbARxqZZZkCAwEAAaNvMG0wHQYDVR0OBBYEFJWwFqmSRGcx
YXmQfdF+XBWkeML4MD4GA1UdIwQ3MDWAFJWwFqmSRGcxYXmQfdF+XBWkeML4oRKk
EDAOMQwwCgYDVQQDEwNmb2+CCQC4VNCHesccEDAMBgNVHRMEBTADAQH/MA0GCSqG
SIb3DQEBBQUAA4GBAIhlUeGZ0d0msNVxYWAXg2lRsJt9INHJQTCJMmoUeTtaRjyp
ffJtuopguNNBDn+MjrEp2/+zLNMahDYLXaTVmBf6zvY0hzB9Ih0kNTh23Fb5j+yK
QChPXQUo0EGCaODWhfhKRNdseUozfNWOz9iTgMGw8eYNLllQRL//iAOfOr/8
</x509cert>
</keyinfo>
]]></example>
</section2>
<section2 topic='OpenPGP' anchor='openpgp'>
<p>OpenPGP (&rfc4880;) defines how to create fingerprints. This fingerprint is used as unique name. The public key data is the OpenPGP public key using binary output. Like X.509 certificates the data must be Base64 encoded to fit in an XML stream.</p>
<example caption='OpenPGP Public Key'><![CDATA[
<keyinfo xmlns='urn:xmpp:tmp:pubkey'>
<name>89d099a3428481cc63fe3fa44e7df2d002b4ce44</name>
<pgpdata>
mQGiBDsKPy8RBACG1vVC8+5jMbtr8YUSfL2ciIu/Zb7/dDhwFd4iFlH7BIEt3RjR
wmiCUw/pcL8LHav7L2L4/Yxm8peJxyK0c11tP5Mq8kG3v55BSkZzn3fwKilEYG1c
rkOPWMEHds3c8kLDn+WNyxrSpw10EyJSsXc0edBdl7eLHiNQsCNmPpZhvwCg8uCQ
...
HDU4Qg9lslDyfa2pHqkweHvC/LmIxrZeCSxOgSMLV8bqbbra1n3F4vdqgc8VP8I2
o9wBSf3HMohGBBgRAgAGBQI7Cj82AAoJEE598tACtM5EuWIAn0tHJF+Bk7pPAngp
hFOdFgS8UBSAAJ9ZPviS2XDzrWRpiyKV+hDqO/WTHA==
</pgpdata>
</keyinfo>
]]></example>
</section2>
<section2 topic='Signatures' anchor='signature'>
<p>Besides the name and the data a key can have one or more signatures. A signature can be used to sign an X.509 certificate with an OpenPGP key or the other way around. This makes it possible to verify a self-signed X.509 certificate with the OpenPGP web-of-trust. A second use case is the concept of user and client keys. A user may choose to use a different X.509 certificate for each client for &xep0178; or &xep0250;. All these client key can be signed by a user key. Once the user key is known all clients can be verified. This XMPP based approach makes it possible to use self-signed certificates without setting up a CA.</p>
<p>The signature has an issuer and the signature data. The issuer contains the unique name / fingerprint of the key that was used to create the signature. An optional argument 'jid' SHOULD be set if the issuer has a different base JID than the key to sign. This makes it possible to find the issuer key using PEP (see <link url='#pub'>Public Key Publication via PEP</link>).</p>
<p>While OpenPGP defines how to sign a string, X.509 does not specify the hash algorithm. For X.509 the signature data MUST contain an attribute what hash and sign algorithms were used. This document only defines 'RSA-SHA1' at this time. To make it easier to use standard cryptographic libraries the hash must contain the ASN.1 BER SHA1 algorithm designator prefix required in PKCS1. See XML-SIG section 6.4.2 how to hash and sign a string using RSA-SHA1. In most cases the cryptographic library will automatically take care of this. The data to sign is the X.509 certificate in DER encoding or the OpenPGP binary string of the fingerprint (the provided key data without Base64 encoding).</p>
<p>The next example contains am X.509 certificate signed by the key defined in the first example.</p>
<example caption='OpenPGP Public Key'><![CDATA[
<keyinfo xmlns='urn:xmpp:tmp:pubkey'>
<name>571b23d99892f4566017426e92c377288ed6c983</name>
<x509cert>
MIICXDCCAcWgAwIBAgIJAKBfLqul2lj3MA0GCSqGSIb3DQEBBQUAMCkxJzAlBgNV
BAMUHmRtZXllckBqYWJiZXIuY29tXDJmdGVzdGNsaWVudDAeFw0wODA5MDYxOTI0
MjVaFw0wOTA5MDYxOTI0MjVaMCkxJzAlBgNVBAMUHmRtZXllckBqYWJiZXIuY29t
XDJmdGVzdGNsaWVudDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwaRLyj7J
/mmliYhjEwGnRGRs6gmcPaIywEK2QLFz6c3/RmRabYbIOE0iZ22D33TguSNQBWfd
lweT3bBETUhd3yuCcqWO5Ptiq/6wulMlxVeV5mxwNP/IF94VPWj0jHbRJcU8ZhS4
UnX6R5q6OSfBGdUU4mYKdiaHpgqTAO9eeqUCAwEAAaOBizCBiDAdBgNVHQ4EFgQU
b8touIdFuXF5clv2I/S1aOOFdN4wWQYDVR0jBFIwUIAUb8touIdFuXF5clv2I/S1
aOOFdN6hLaQrMCkxJzAlBgNVBAMUHmRtZXllckBqYWJiZXIuY29tXDJmdGVzdGNs
aWVudIIJAKBfLqul2lj3MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEA
pA5tI1J9Qpn3jSoQctFksRLb2H3A48R3rU8/qnarwE/AyOvth3k3ulLEmhJBT+0S
mVb6WzrZEA/2plu7DhR8ylhuvJv6cAEIN+TPha3yzO2P8uoVZf7hdunOhMLl2Z6w
xEfiGI5X9OsaMeFOQa+B2C3uUVAMLbVV7Rp/qQkai1Y=
</x509cert>
<signature>
<issuer>428b1358a286430f628da23fb33ddaf6e474f5c5</issuer>
<value method='RSA-SHA1'>
E3q/UkjRR3zcZMcIIoE2sSVKUATl26zyzO1Pmoe96p8apW91c3a0KqkQp1ZMBqXX
+e2ImqQ79CKv+9qzXitxx+V4EcniKN0ZsSR+9ZbfflxkOvmBa2rpq9hFE1NYyfuT
fsAZkRhAGlP7P5ELcvhqJ4WL6qBPYQU2NEnbVlcZSbA=
</value>
</signature>
</keyinfo>
]]></example>
</section2>
</section1>
<section1 topic='Public Key Publication via PEP' anchor='pub'>
<p>An entity SHOULD follow the best practices defined in &xep0222; to publish its long-term public keys via its own server. Processes for doing so are described in the following sections.</p>
<section2 topic='Creating the Node' anchor='pub-create'>
@ -84,7 +178,7 @@
<ul>
<li>Items published to the node are persistent (this is done by setting the "persist_items" option to true).</li>
<li>Keys will be pushed to subscribers only when new keys are published, not when subscribers become newly available or when a new subscription is created (this is done by setting the "send_last_published_item" option to "never").</li>
</ul>
</ul>
<p>If the user wants to control access to his/her identity (see <link url='#security'>Security Considerations</link>) then the node access model SHOULD be something other than "open" (this can be done by setting the "access_model" option to a value of "authorize", "presence", "roster", or "whitelist").</p>
<example caption='Entity Creates Node'><![CDATA[
<iq type='set'
@ -120,16 +214,11 @@
<iq from='juliet@capulet.com/balcony' type='set' id='pub1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<publish node='urn:xmpp:tmp:pubkey'>
<item id='julietRSAkey1hash'>
<KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
<KeyName>julietRSAkey1hash</KeyName>
<KeyValue>
<RSAKeyValue>
<Modulus>...</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
</KeyValue>
</KeyInfo>
<item id='julietPGPkey1hash'>
<keyinfo>
<name>julietPGPkey1hash</name>
<openpgp>...</openpgp>
</keyinfo>
</item>
</publish>
<configure>
@ -156,67 +245,24 @@
]]></example>
</section2>
<section2 topic='Publishing a Key' anchor='pub-publish'>
<p>The entity publishes a key by sending a pubsub publish request to the pubsub service. A previously published key can be updated by re-publishing the key using the same ItemID.</p>
<p>Each public key MUST be wrapped in a &lt;KeyInfo/&gt; element qualified by the 'http://www.w3.org/2000/09/xmldsig#' namespace as specified in &w3xmlsig;. Each &lt;KeyInfo/&gt; element MUST contain a &lt;KeyName/&gt; element with a name that is unique for the user; this enables the key to be referenced by other XMPP Extension Protocols (for example, &xep0136;). The name MAY be the same as the value of the ItemID. However, if two &lt;KeyInfo/&gt; elements contain the same public key in different formats (for example, an X.509 certificate may contain an RSA key), then the name of the two keys SHOULD be the same.</p>
<p>Before computing the fingerprint or publishing the key, all character data <em>between</em> all elements in the &lt;KeyInfo/&gt; element MUST be removed and the XML MUST be converted to canonical form according to &w3canon;. (Any whitespace or other character data shown in the examples herein is included only for the purpose of readability.)</p>
<p>The value of the ItemID SHOULD be set to the fingerprint of the public key, e.g., the SHA256 hash (see &nistfips180-2;) of the key's normalized &lt;KeyValue/&gt;, &lt;PGPData/&gt; or &lt;X509Data/&gt; element. Therefore subscribers or other interested entities are able to request a single key by specifying its fingerprint (for example, when a subscriber is using the &xep0116; protocol).</p>
<example caption='Entity Publishes a DSA Key to its Server'><![CDATA[
<iq from='juliet@capulet.com/balcony' type='set' id='pub2'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<publish node='urn:xmpp:tmp:pubkey'>
<item id='julietDSAkey1hash'>
<KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
<KeyName>julietDSAkey1hash</KeyName>
<KeyValue>
<DSAKeyValue>
<P>...</P>
<Q>...</Q>
<G>...</G>
<Y>...</Y>
</DSAKeyValue>
</KeyValue>
</KeyInfo>
</item>
</publish>
</pubsub>
</iq>
]]></example>
<p>The entity publishes a key by sending a pubsub publish request to the pubsub service. A previously published key can be updated by re-publishing the key using the same ItemID. The value of the ItemID SHOULD be set to the fingerprint of the public key (the name). Therefore subscribers or other interested entities are able to request a single key by specifying its fingerprint (for example, when a subscriber is using C2C Authentication Using TLS).</p>
<example caption='Entity Publishes an X.509 Certificate to its Server'><![CDATA[
<iq from='juliet@capulet.com/balcony' type='set' id='pub3'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<publish node='urn:xmpp:tmp:pubkey'>
<item id='julietX509cert1hash'>
<KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
<KeyName>julietX509cert1hash</KeyName>
<X509Data>
<X509IssuerSerial>
<X509IssuerName>CN=TAMURA Kent, OU=TRL, O=IBM, L=Yamato-shi, ST=Kanagawa, C=JP</X509IssuerName>
<X509SerialNumber>12345678</X509SerialNumber>
</X509IssuerSerial>
<X509SKI>31d97bd7</X509SKI>
<X509SubjectName>Subject of Certificate B</X509SubjectName>
<X509Certificate>...</X509Certificate>
<X509Certificate>...</X509Certificate>
<X509Certificate>...</X509Certificate>
</X509Data>
</KeyInfo>
</item>
</publish>
</pubsub>
</iq>
]]></example>
<example caption='Entity Publishes a PGP Key to its Server'><![CDATA[
<iq from='juliet@capulet.com/balcony' type='set' id='pub4'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<publish node='urn:xmpp:tmp:pubkey'>
<item id='julietPGPkey1hash'>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<KeyName>julietPGPkey1hash</KeyName>
<PGPData>
<PGPKeyId>...</PGPKeyId>
<PGPKeyPacket>...</PGPKeyPacket>
</PGPData>
</KeyInfo>
<keyinfo'>
<name>julietX509cert1hash</name>
<x509cert>
...
</x509cert>
<signature>
<issuer>julietPGPkey1hash</issuer>
<value>
...
</value>
</signature>
</keyinfo>
</item>
</publish>
</pubsub>
@ -227,16 +273,19 @@
<message to='romeo@montague.net/garden' from='juliet@capulet.com' type='headline'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='urn:xmpp:tmp:pubkey'>
<item id='julietRSAkey1hash'>
<KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
<KeyName>julietRSAkey1hash</KeyName>
<KeyValue>
<RSAKeyValue>
<Modulus>...</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
</KeyValue>
</KeyInfo>
<item id='julietX509cert1hash'>
<keyinfo'>
<name>julietX509cert1hash</name>
<x509cert>
...
</x509cert>
<signature>
<issuer>julietPGPkey1hash</issuer>
<value>
...
</value>
</signature>
</keyinfo>
</item>
</items>
</event>
@ -267,29 +316,17 @@
id='items1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<items node='urn:xmpp:tmp:pubkey'>
<item id='julietRSAkey1hash'>
<KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
<KeyName>julietRSAkey1hash</KeyName>
<item id='julietPGPkey1hash'>
<keyinfo'>
<name>julietPGPkey1hash</name>
...
</KeyInfo>
</item>
<item id='julietDSAkey1hash'>
<KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
<KeyName>julietDSAkey1hash</KeyName>
...
</KeyInfo>
</keyinfo>
</item>
<item id='julietX509cert1hash'>
<KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
<KeyName>julietX509cert1hash</KeyName>
<keyinfo'>
<name>julietX509cert1hash</name>
...
</KeyInfo>
</item>
<item id='julietPGPkey1hash'>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<KeyName>julietPGPkey1hash</KeyName>
...
</KeyInfo>
</keyinfo>
</item>
</items>
</pubsub>
@ -302,7 +339,7 @@
id='items2'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<items node='urn:xmpp:tmp:pubkey'>
<item id='julietRSAkey1hash'/>
<item id='julietX509cert1hash'/>
</items>
</pubsub>
</iq>
@ -314,16 +351,11 @@
id='items2'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<items node='urn:xmpp:tmp:pubkey'>
<item id='julietRSAkey1hash'>
<KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
<KeyName>julietRSAkey1hash</KeyName>
<KeyValue>
<RSAKeyValue>
<Modulus>...</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
</KeyValue>
</KeyInfo>
<item id='julietX509cert1hash'>
<keyinfo'>
<name>julietX509cert1hash</name>
...
</keyinfo>
</item>
</items>
</pubsub>
@ -348,18 +380,12 @@
to='romeo@montague.net/garden'
from='juliet@capulet.com/balcony'>
<pubkeys xmlns='urn:xmpp:tmp:pubkey'>
<KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
<keyinfo>
...
</KeyInfo>
<KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
</keyinfo>
<keyinfo>
...
</KeyInfo>
<KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
...
</KeyInfo>
<KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
...
</KeyInfo>
</keyinfo>
</pubkeys>
</iq>
]]></example>
@ -382,8 +408,8 @@
to='juliet@capulet.com/balcony'
from='romeo@montague.net/garden'>
<pubkeys xmlns='urn:xmpp:tmp:pubkey'>
<fprint>julietRSAkey1hash</fprint>
<fprint>julietRSAkey2hash</fprint>
<fprint>julietX509cert1hash</fprint>
<fprint>julietX509cert2hash</fprint>
</pubkeys>
</iq>
]]></example>
@ -393,12 +419,12 @@
to='romeo@montague.net/garden'
from='juliet@capulet.com/balcony'>
<pubkeys xmlns='urn:xmpp:tmp:pubkey'>
<KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
<keyinfo>
...
</KeyInfo>
<KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
</keyinfo>
<keyinfo>
...
</KeyInfo>
</keyinfo>
</pubkeys>
</iq>
]]></example>
@ -420,12 +446,12 @@
to='romeo@montague.net/garden'
from='juliet@capulet.com/balcony'>
<pubkeys xmlns='urn:xmpp:tmp:pubkey' jid='benvolio@montague.net'>
<KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
<keyinfo>
...
</KeyInfo>
<KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
</keyinfo>
<keyinfo>
...
</KeyInfo>
</keyinfo>
</pubkeys>
</iq>
]]></example>
@ -448,22 +474,12 @@
<message to='romeo@montague.net/garden'
from='juliet@capulet.com/balcony'>
<pubkeys xmlns='urn:xmpp:tmp:pubkey' jid='benvolio@montague.net'>
<KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
<KeyValue>
<RSAKeyValue>
<Modulus>...</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
</KeyValue>
</KeyInfo>
<KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
<KeyValue>
<RSAKeyValue>
<Modulus>...</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
</KeyValue>
</KeyInfo>
<keyinfo>
...
</keyinfo>
<keyinfo>
...
</keyinfo>
</pubkeys>
</message>
]]></example>
@ -496,18 +512,37 @@
<xs:element name='pubkeys'>
<xs:complexType>
<xs:choice
xmlns:dsig='http://www.w3.org/2000/09/xmldsig#'
maxOccurs='unbounded'
minOccurs='0'>
<xs:choice>
<xs:element name='fprint' type='xs:string'/>
<xs:element ref='dsig:KeyInfo'/>
<xs:element ref='keyinfo'/>
</xs:choice>
<xs:attribute name='jid' type='xs:string' use='optional'/>
<xs:anyAttribute namespace='##any' processContents='lax'/>
</xs:complexType>
</xs:element>
<xs:element name='keyinfo'>
<xs:complexType>
<xs:element name='name' minOccurs='1' maxOccurs='1' type='xs:string'/>
<xs:choice minOccurs='0' maxOccurs='1'>
<xs:element name='x509' type='xs:string'/>
<xs:element name='openpgp' type='xs:string'/>
</xs:choice>
<xs:element ref='signature' minOccurs='0' maxOccurs='unbound'/>
</xs:complexType>
</xs:element>
<xs:element name='signature'>
<xs:complexType>
<xs:element name='issuer' type='xs:string'>
<xs:attribute name='jid' type='xs:string' use='optional'/>
</<xs:element>
<xs:element name='value' type='xs:string'>
<xs:attribute name='method' type='xs:string' use='optional'/>
</<xs:element>
</xs:complexType>
</xs:element>
</xs:schema>
]]></code>
</section1>