Generate XML Signature


Tue Jul 05 2022 14:57:47 GMT+0000 (UTC)

Saved by @Justus #apex

public static String generateXMLSignature(String docBodyString){
	// 1. Apply the Transforms, as determined by the application, to the data object.
	// (no transforms are done, since the body should be delivered in canonicalized form ( offers no canonicalization algorithm))
	// 2. Calculate the digest value over the resulting data object. 
	Blob bodyDigest = Crypto.generateDigest('SHA1',Blob.valueOf(docBodyString));
	// 3. Create a Reference element, including the (optional) identification of the data object, any (optional) transform elements, the digest algorithm and the DigestValue.
	// (Note, it is the canonical form of these references that are signed and validated in next steps.)

	String referenceString = '';
	referenceString += '';
	referenceString += '<ds:Reference URI="#msgBody">';
	referenceString += '<ds:Transforms>';
	referenceString += '<ds:Transform Algorithm=""></ds:Transform>';
	referenceString += '<ds:Transform Algorithm=""></ds:Transform>';
	referenceString += '</ds:Transforms>';
	referenceString += '<ds:DigestMethod Algorithm=""></ds:DigestMethod>';
	referenceString += '<ds:DigestValue>'+EncodingUtil.base64Encode(bodyDigest)+'</ds:DigestValue>';
	referenceString += '</ds:Reference>';		 
	// 4. Create SignedInfo element with SignatureMethod, CanonicalizationMethod and Reference(s).
	String signedInfoString = '';
	signedInfoString += '<ds:SignedInfo xmlns:ds="">';
	signedInfoString += '<ds:CanonicalizationMethod Algorithm=""></ds:CanonicalizationMethod>';
	signedInfoString += '<ds:SignatureMethod Algorithm=""></ds:SignatureMethod>';
	signedInfoString += referenceString;
	signedInfoString += '</ds:SignedInfo>';
	// 5. Canonicalize and then calculate the SignatureValue over SignedInfo based on algorithms specified in SignedInfo.
	// (no canonicalization is done, since the signedinfo element should be delivered in canonicalized form ( offers no canonicalization algorithm))

	String algorithmName = 'RSA-SHA1';
	// decrypted private key pkcs8 format from certificate
	String key = '[decryptedPrivateKeypkcs8formatfromcertificate]';
	Blob privateKey = EncodingUtil.base64Decode(key);
	Blob siBlob = Blob.valueOf(signedInfoString);
	Blob signatureValue = Crypto.sign(algorithmName, siBlob, privateKey);
	String signatureValueString = EncodingUtil.base64Encode(signatureValue);

	// 6. Construct the Signature element that includes SignedInfo, Object(s) (if desired, encoding may be different than that used for signing), KeyInfo (if required), and SignatureValue. 
	String signatureString = '';
	signatureString += '<ds:Signature xmlns:ds="">';
	signatureString += signedInfoString; 
	signatureString += '<ds:SignatureValue xmlns:ds="">'+signatureValueString+'</ds:SignatureValue>';
	signatureString += '<ds:KeyInfo xmlns:ds="">';
	signatureString += '<ds:X509Data xmlns:ds="">';
	signatureString += '<ds:X509Certificate xmlns:ds="">[the certificate used for signing]</ds:X509Certificate>';
	signatureString += '</ds:X509Data>';
	signatureString += '</ds:KeyInfo>';
	signatureString += '</ds:Signature>';
	return signatureString;