Validating peppol ids

following Peppol EBMS:0004 – SMP metadata fetch failure when sending BIS Billing 3.0 invoice - #9 by ced , I start a new discussion since the original one is closed.

I searched a bit and it seams possible to validate peppol ids using dns.

The peppol network uses dns NAPTR records to find where (as in which access point) to send documents for a particular peppol id.

Using Peppol Practical - Participant Information I was able to find my company info, including the associated dns record. Then I can query that record using standard dns tools:

dig naptr $RECORD

This gives my peppol access point technical name.

If the id is not on the peppol network, resolution fails.

Now to get the dns record to use, the algorithm seems easy enough:

strip-trailing(base32(sha-256(lowercase(ID-VALUE))),"=")+"."+ID-SCHEME+"."+DNSZONE
ID-SCHEME is part of the input parameter - the scheme part of the participant identifier (usually this is iso6523-actorid-upis)
ID-VALUE is also part of the input parameter - the value part of the participant identifier
DNSZONE is the DNS zone in which the SML operates - for the production SML that is participant.sml.prod.tech.peppol.org and for the test SMK this is participant.sml.test.tech.peppol.org

Seems simple enough, but I have not been able to make it work even to recreate my own record… And I couldn’t find examples, so I don’t know where my error is (the id ? the hash ? the base32 ?).

But I’m also not a programmer, so I don’t doubt that it would be simple for you to do it, and then you have a fast, easy, and independant method to check peppol id validity. On the test and production networks.

did it :grinning_face:

import hashlib
import base64

def peppol_sml_dns_name(
    participant_id: str,
    scheme: str = "iso6523-actorid-upis",
    sml_zone: str = "participant.sml.prod.tech.peppol.org",
) -> str:
    """
    Create the DNS name used for Peppol SML NAPTR lookup.

    Example input:
        participant_id = "0088:123456789"

    Result:
        <base32(sha256(lowercase(id)))>.<scheme>.<sml_zone>
    """

    lowercase = participant_id.lower()

    sha256_digest = hashlib.sha256(
        lowercase.encode("utf-8")
    ).digest()

    # Base32 encoding
    encoded = base64.b32encode(sha256_digest).decode("ascii")

    # Remove trailing '=' padding
    encoded = encoded.rstrip("=")

    return f"{encoded}.{scheme}.{sml_zone}"

Probably it can be cleaned up…

Now if the resulting naptr record can be resolved, it means that the participant exists on the network.

And you have the SMP that you can querry to see which documents are accepted.

I’m wondering if DNS record existence is enough to consider that the participant ID is usable. Should not the content of the NAPTR be parsed and resolved also?
Also NAPTR queries may not be supported by all DNS softwares.

So for me it sounds like a complex solution compare to Peppol Lookup Service - OpenPeppol

I couldn’t find it, does the peppol lookup service offer an api ?

yes if you want to validate the documents that the participant accepts, you have to querry the SMP (provided by the dns) and parse the answer. It shouldn’t be much more difficult than parsing the answer from peppol lookup service (but maybe I’m wrong, again, I’m really not a programmer) and it removes a layer between tryton and the data that it needs.

Except azure (but who cares), the dns systems that do not support dns naptr are really fringe cases

Now, really, the decision is yours to make, I just wanted to share my findings :smiley: