iDEAL implementatie in Perl

1
Hallo allemaal,

Ik ben bezig met een iDEAL implementatie in Perl en ik loop al meteen vast op het eerste gedeelte: het signeren van een XML bericht. Voordat ik inga op de specifieke problemen, zou ik eerst graag de code-flow met jullie willen doornemen. Wellicht dat ik daar al een fout maak. Als voorbeeld gebruik ik een DirectoryReq. Daar gaat-ie:
  1. Genereer DirectoryReq XML
  2. Canonicaliseer deze XML (middels inc-C14N)
  3. Genereer hash van gecanonicaliseerde XML (middels SHA256)
  4. Encode hash met base64
  5. Stop deze encoded hash in de SignedInfo node (als "DigestValue")
  6. Canonicaliseer de SignedInfo node (middels exc-C14N)
  7. Signeer de gecanonicaliseerde node met je private key (middels RSAWithSHA256)
  8. Encode deze signature met base64
  9. Stop deze encoded signature in de SignatureValue
  10. Creëer fingerprint van je public key
  11. Stop deze fingerprint in KeyName
  12. Injecteer complete Signature in je XML
En nu wat uitgebreider:

1. Genereer DirectoryReq XML

Code: Selecteer alles

<?xml version="1.0" encoding="UTF-8"?>
<DirectoryReq xmlns="http://www.idealdesk.com/ideal/messages/mer-acq/3.3.1" version="3.3.1">
  <createDateTimestamp>2014-02-03T13:35:23.000Z</createDateTimestamp>
  <Merchant>
    <merchantID>XXXXXXXXX</merchantID>
    <subID>0</subID>
  </Merchant>
</DirectoryReq>
2. Canonicaliseer deze XML (middels inc-C14N)
3. Genereer hash van gecanonicaliseerde XML (middels SHA256)
4. Encode hash met base64

5. Stop deze encoded hash in de SignedInfo node (als "DigestValue")

Code: Selecteer alles

    <SignedInfo>
      <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
      <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
      <Reference URI="">
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
        <DigestValue>FftEUkYUIdveuSIgZvGRlb4L0c3ex19I1HYSzN2Do3c=</DigestValue>
      </Reference>
    </SignedInfo>
6. Canonicaliseer de SignedInfo node (middels exc-C14N)
7. Signeer de gecanonicaliseerde node met je private key (middels RSAWithSHA256)
8. Encode deze signature met base64

9. Stop deze encoded signature in de SignatureValue

Code: Selecteer alles

    <SignatureValue>
F2U11Aevnox+hWbfQgvUqSgz9JgdKjAO0FUdmoZMbRBUBx827e1DIpB5ybTdo7GUw0uAymLBsGNp
i++yQdJDh9ZnGBvmmg24VnvVpCYtPhSReBXbCi5NaGkJDN6csiEfJGytUhaaJJ02iAS2Es3ADDrr
d86JGLYDPrf63fo8CXZKi2H37OONDWzcBUEFfrnoQud8FCcBrY5ESFyxFOJ0C99VYJZC9qO8ehWb
aNee3h7wr4ZNwz8+iQWjUrbl+xG6gBog9FwSTQ7u9uGbeTslJ8qNqHaYgvb4J8avZZ3Io8PfEy5z
B0bzB38650Z5fJVWluxKvKF9X+TTuavzi+F69g==
    </SignatureValue>
10. Creëer fingerprint van je public key

11. Stop deze fingerprint in KeyName

Code: Selecteer alles

    <KeyInfo>
      <KeyName>A500E84D81D78309634B616BA4761D0943781D28</KeyName>
    </KeyInfo>
12. Injecteer complete Signature in je XML

Code: Selecteer alles

<?xml version="1.0" encoding="UTF-8"?>
<DirectoryReq xmlns="http://www.idealdesk.com/ideal/messages/mer-acq/3.3.1" version="3.3.1">
  <createDateTimestamp>2014-02-03T13:35:23.000Z</createDateTimestamp>
  <Merchant>
    <merchantID>XXXXXXXXX</merchantID>
    <subID>0</subID>
  </Merchant>
  <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/2001/04/xmldsig-more#rsa-sha256" />
      <Reference URI="">
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
        <DigestValue>FftEUkYUIdveuSIgZvGRlb4L0c3ex19I1HYSzN2Do3c=</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>
F2U11Aevnox+hWbfQgvUqSgz9JgdKjAO0FUdmoZMbRBUBx827e1DIpB5ybTdo7GUw0uAymLBsGNp
i++yQdJDh9ZnGBvmmg24VnvVpCYtPhSReBXbCi5NaGkJDN6csiEfJGytUhaaJJ02iAS2Es3ADDrr
d86JGLYDPrf63fo8CXZKi2H37OONDWzcBUEFfrnoQud8FCcBrY5ESFyxFOJ0C99VYJZC9qO8ehWb
aNee3h7wr4ZNwz8+iQWjUrbl+xG6gBog9FwSTQ7u9uGbeTslJ8qNqHaYgvb4J8avZZ3Io8PfEy5z
B0bzB38650Z5fJVWluxKvKF9X+TTuavzi+F69g==
    </SignatureValue>
    <KeyInfo>
      <KeyName>A500E84D81D78309634B616BA4761D0943781D28</KeyName>
    </KeyInfo>
  </Signature>
</DirectoryReq>
Er zijn twee dingen die ik zeker weet:
  • De DigestValue is goed
  • De KeyName is goed
Maar de Aquirer blijft maar "Invalid electronic signature" terugsturen.

In sommige (niet alle) documentatie over XML Signing staat nog een extra stap die ik overigens niet terug kan vinden in de officiële iDEAL documentatie. Die stap zit dan tussen stap 6 en 7. In plaats dat je de gecanonicaliseerde versie van SignedInfo signeert, maak je eerst een hash van SignedInfo en signeer je de hash.

Heb ik de flow goed? Moet die extra stap er tussen?