Most important: <ds:SignatureValue>
must contain the digital signature (SHA256-RSA encrypted hash) of the raw, minified, canonicalized XML output of <Invoice>
— before any hashing, not the full invoice or the Signature block itself.
What is DS333?
DS333 is an IRBM e-Invoice error that means the digest or signature of the <Invoice>
block is incorrect. This is a cryptographic failure — the server re-calculates the hash of your minified Invoice
block and compares it against what you signed. If they don’t match, you get:
"DS333: Signature digest mismatch"
Why does DS333 happen?
- ❌ You signed
SignedInfo
before finalizing all child nodes (e.g. Reference, CanonicalizationMethod) - ❌ You hashed the wrong thing (e.g. Invoice, Signature, whole document)
- ❌ You didn’t canonicalize
<SignedInfo>
using Exclusive C14N - ❌ You inserted placeholder or signed an XML with whitespace differences
Fix Strategy (Laravel + xmlseclibs)
Step 1: Canonicalize & Sign SignedInfo Block
After building <SignedInfo>
including Reference + Digest, do this:
$signedInfoXml = $objDSig->sigNode->getElementsByTagName('SignedInfo')->item(0)->C14N(true, false);
$privateKey = openssl_pkey_get_private($this->pkeyPem, $this->pkeyPassphrase);
openssl_sign($signedInfoXml, $signatureBin, $privateKey, OPENSSL_ALGO_SHA256);
$signatureValue = base64_encode($signatureBin);
Step 2: Insert SignatureValue
$signatureValueNode = $doc->createElementNS($ds, 'ds:SignatureValue', $signatureValue);
$signatureNode->appendChild($signatureValueNode);
Step 3: Canonicalize using Exclusive C14N
Inside <SignedInfo>
tag:
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
Do not use inclusive or default Canonicalization.
Correct Signing Order
- Create full UBL XML (with UBLExtensions and placeholder)
- Build
<SignedInfo>
with Reference and Digest - Canonicalize SignedInfo
- Generate SignatureValue using SHA256 + private key
- Insert
SignatureValue
into Signature block - Insert
KeyInfo
with X509Certificate - Place entire
<ds:Signature>
inside<ext:UBLExtensions>
Validation Tip
$canonicalSignedInfo = $signedInfoNode->C14N(true, false);
$hashCheck = base64_encode(hash('sha256', $canonicalSignedInfo, true));
Log::debug('SignedInfo Digest', [$hashCheck]);
Common Mistakes to Avoid
- ❌ Signing the whole invoice instead of Invoice
- ❌ Inserting SignatureValue before completing Reference block
- ❌ Using non-canonicalized XML with extra spaces or formatting
Summary
DS333 is fixed by properly signing <Invoice>
using:
- Exclusive C14N
- SHA256 hash
- RSA private key
- Accurate and final XML block with all Reference data included
Never sign before building the exact final version of <Invoice>
.