CryptoSys Home > PKI > Creating output for secure XML documents

Creating output for secure XML documents


This page expands the manual page Using output in XML documents and gives some sample code.

New2020-12-07: For a more detailed look at encryption in XML documents see Using CryptoSys PKI to encrypt and decrypt using XMLENC and its companion explanatory page Encryption in XML documents using XMLENC.

You can use CryptoSys PKI Pro to create most of the cryptographic elements required in the [XML-DSIG] and [XML-ENC] specifications to insert into XML documents.

In general, work using byte arrays and then use CNV_B64StrFromBytes or Cnv.ToBase64 to convert byte arrays into base64 encoding.

Here is a selection of some elements you can create. The test files are in pki_pro_files.zip (7 kB).

DigestValue | SignatureValue | X509Certificate | X509IssuerSerial | X509IssuerName | X509SubjectName | RSAKeyValue | RSAKeyPair | CipherValue | References | Contact us

DigestValue element

Use Hash.BytesFromBytes or Hash.BytesFromFile then Cnv.ToBase64.

// Compute sha1 digest value of canonicalized object
// NB You must do your own canonicalization!
string digval = Cnv.ToBase64(Hash.BytesFromFile("xmldsig-object-c14n.txt", HashAlgorithm.Sha1));
Console.WriteLine("<DigestValue>" + digval + "</DigestValue>");
<DigestValue>OPnpF/ZNLDxJ/I+1F3iHhlmSwgo=</DigestValue>

SignatureValue element

Use Sig.SignData or Sig.SignFile.

// Compute rsa-sha1 signature value of c14n'd signed-info element using Alice's private key
string sigval = Sig.SignFile("xmldsig-signedinfo-c14.txt", "alice.key", "password", SigAlgorithm.Rsa_Sha1);
Console.WriteLine("SignatureValue: " + sigval);
SignatureValue: nihUFQg4mDhLgecvhIcKb9Gz8VRTOlw+adiZOBBXgK4JodEe5aFfCqm8WcRIT8GL
LXSk8PsUP4//SsKqUBQkpotcAqQAhtz2v9kCWdoUDnAOtFZkd/CnsZ1sge0ndha40wWDV+nOWyJxkYgi
cvB8POYtSmldLLepPGMz+J7/Uws=

Alternatively, use Rsa.EncodeMsgForSignature followed by Rsa.RawPrivate then Cnv.ToBase64.

X509Certificate element

Use X509.ReadStringFromFile.

// Create X509Certificate element
string s = X509.ReadStringFromFile("smallca.cer");
Console.WriteLine("X509Certificate:\n" + s);
X509Certificate:
MIHgMIGaAgEBMA0GCSqGSIb3DQEBBQUAMAwxCjAIBgNVBAMTAUEwHhcNOTkwOTE5MDEwODQ3WhcNMzkx
MjMxMjM1OTU5WjAMMQowCAYDVQQDEwFBMEowDQYJKoZIhvcNAQEBBQADOQAwNgIxAvkJan2DVcJxrvFq
y0VBurMiooO1rd5w4zcZp8m77nZL4vy4XMeb4j8nH2+3tTaAGQIBAzANBgkqhkiG9w0BAQUFAAMyAAGa
m7Lsuc39ZsaUWy7Wltwyh2jaXm8uXVp/5gkuYI+MRaUYfgYc6YGq6tby4xR9JZE=

X509IssuerSerial element

Use X509.QueryCert with query "serialNumber" and X509.Options.Decimal.

// Create X509IssuerSerial element
string cerFile = "alice.cer"; 
string s = X509.QueryCert(cerFile, "serialNumber", X509.Options.Decimal);
Console.WriteLine("X509IssuerSerial: " + s);
X509IssuerSerial: 93318145165434344057210696409401045936

X509IssuerName element

Use X509.QueryCert with query "issuerName" and X509.Options.Ldap.

// Create X509IssuerName element
string s = X509.QueryCert(cerFile, "IssuerName", X509.Options.Ldap);
Console.WriteLine("X509IssuerName: " + s);
X509IssuerName: CN=CarlRSA

X509SubjectName element

Use X509.QueryCert with query "subjectName" and X509.Options.Ldap.

// Create X509SubjectName element
string s = X509.QueryCert(cerFile, "subjectName", X509.Options.Ldap);
Console.WriteLine("X509SubjectName: " + s);
X509SubjectName: CN=AliceRSA

RSAKeyValue element

Use Rsa.KeyValue or Rsa.ToXMLString.

// Create RSAKeyValue element (the public key)
string pubkey = Rsa.ReadPublicKey("alice.cer").ToString();
s = Rsa.KeyValue(pubkey, "Modulus");
Console.WriteLine("RSAKeyValue Modulus: " + s);
s = Rsa.KeyValue(pubkey, "Exponent");
Console.WriteLine("RSAKeyValue Exponent: " + s);
RSAKeyValue Modulus: 4IlzOY3Y9fXoh3Y5f06wBbtTg94Pt6vcfcd1KQ0FLm0S36aGJtTSb6pYKfy
X7PqCUQ8wgL6xUJ5GRPEsu9gyz8ZobwfZsGCsvu40CWoT9fcFBZPfXro1Vtlh/xl/yYHm+Gzqh0Bw76x
tLHSfLfpVOrmZdwKmSFKMTvNXOFd0V18=
RSAKeyValue Exponent: AQAB

RSAKeyPair element

Use Rsa.ToXMLString.

// Create RSAKeyPair element (the full private key)
string prikey = Rsa.ReadPrivateKey("alice.key", "password").ToString();
s = Rsa.ToXMLString(prikey, 0);
Console.WriteLine("RSAKeyPair:\n" + s);
RSAKeyPair:
<RSAKeyPair><Modulus>4IlzOY3Y9fXoh3Y5f06wBbtTg94Pt6vcfcd1KQ0FLm0S36aGJtTSb6pYKfy
X7PqCUQ8wgL6xUJ5GRPEsu9gyz8ZobwfZsGCsvu40CWoT9fcFBZPfXro1Vtlh/xl/yYHm+Gzqh0Bw76x
tLHSfLfpVOrmZdwKmSFKMTvNXOFd0V18=</Modulus><Exponent>AQAB</Exponent><P>9tbgIiFMX
wpw/yf85bNQap3lD7WFlsZA+qgKtJubDFXCAR35N4KKFMjykw6SzaVmIbk80ga/tFUxydytypgt0Q==<
/P><Q>6N6wESUJ0gJRAd6K6JhQ9Xd3YaRFk2sIVZZzXfTIWxKTInOLf9Nwf/Wkqrt0/Twiato4kSqGW2
wU6K5MnvqOLw==</Q><DP>l0zwh5sXf+4bgxsUtgtqkF+GJ1Hht6B/9eSI41m5+R6b0yl3OCJI1yKxJZ
i6PVlTt/oeILLIURYjdZNR56vN8Q==</DP><DQ>LPAkW/qgzYUi6tBuT/pszSHTyOTxhERIZHPXKY9+R
ozsFd7kUbOU5yyZLVVleyTqo2IfPmxNZ0ERO+G+6YMCgw==</DQ><InverseQ>WIjZoVA4hGqrA7y730
v0nG+4tCol+/bkBS9u4oiJIW9LJZ7Qq1CTyr9AcewhJcV/+wLpIZa4M83ixpXub41fKA==</InverseQ
><D>pAPDJ0d2NDRspoa1eUkBSy6K0shissfXSAlqi5H3NvJ11ujNFZBgJzFHNWRNlc1nY860n1asLzdu
HO4Ovygt9DmQbzTYbghb1WVq2EHzE9ctOV7+M8v/KeQDCz0Foo+38Y6idjeweVfTLyvehwYifQRmXskb
r4saw+yRRKt/IQ==</D></RSAKeyPair>

CipherValue element

xmlenc#rsa-1_5: Use Rsa.EncodeMsgForEncryption with Rsa.EME.PKCSv1_5 option followed by Rsa.RawPublic then Cnv.ToBase64

// Content encryption key to be transported
byte[] cek = Cnv.FromHex("737C791F25EAD0E04629254352F7DC6291E5CB26917ADA32");
// Read in recipient's public key to ephemeral "internal" string
string pubkey = Rsa.ReadPublicKey("bob.cer").ToString();
// Get required size of encryption block
int nbytes = Rsa.KeyBytes(pubkey);
// Encode the message for encryption
byte[] block = Rsa.EncodeMsgForEncryption(nbytes, cek, Rsa.EME.PKCSv1_5);
// Encrypt with RSA key
block = Rsa.RawPublic(block, pubkey);
// Output encoded in base64
Console.WriteLine("xmlenc#rsa-1_5\nCipherValue: " + Cnv.ToBase64(block));
xmlenc#rsa-1_5
CipherValue: QPkP6v10fbcR8ly9d+pLop/Aszjxop9XoiKuYZmm5bfNfc0GUdhpnHkpGEEEkRrBgN0
hV0vd+zKlv/T3s+HMtm6aTwI790MKwA0VO/4QafLvf6Nh6igZlvsrJXuSiPnuige/oQ/RPA89Ml3Py+r
q10RahNu+32kXJPsgwi0ntWs=

xmlenc#rsa-oaep-mgf1p: As for xmlenc#rsa-1_5 except use Rsa.EME.OAEP option.

xmlenc#tripledes-cbc: Use Cipher.Encrypt with options CipherAlgorithm.Tdea, Mode.CBC and Padding.Pkcs5, then use Cnv.ToBase64 after prepending the IV to the ciphertext.

// Content to be encrypted (From S/MIME Examples)
byte[] msg = Encoding.ASCII.GetBytes("This some sampe content.");
// 192-bit tripledes key
byte[] cek = Cnv.FromHex("737C791F25EAD0E04629254352F7DC6291E5CB26917ADA32");
// Initialization vector
byte[] iv = Cnv.FromHex("B36B6BFB6231084E");
// Ciphertext = D76FD1178FBD02F84231F5C1D2A2F74A4159482964F675248254223DAF9AF8E4
byte[] ct = Cipher.Encrypt(msg, cek, iv, CipherAlgorithm.Tdea, Mode.CBC, Padding.Pkcs5);
// Prepend IV, i.e. concatenate IV + ciphertext
// B36B6BFB6231084E || D76FD1178FBD02F84231F5C1D2A2F74A4159482964F675248254223DAF9AF8E4
byte[] value = new byte[iv.Length + ct.Length];
System.Buffer.BlockCopy(iv, 0, value, 0, iv.Length);
System.Buffer.BlockCopy(ct, 0, value, iv.Length, ct.Length);
// Output encoded in in base64 
Console.WriteLine("xmlenc#tripledes-cbc\nCipherValue: " + Cnv.ToBase64(value));
xmlenc#tripledes-cbc
CipherValue: s2tr+2IxCE7Xb9EXj70C+EIx9cHSovdKQVlIKWT2dSSCVCI9r5r45A==

Note that the padding for block ciphers described in section 5.2 of XML-ENC is similar to PKCS#5 but also allows arbitrary padding bytes. PKCS#5 padding is always valid when encrypting, but you may need to use the Padding.NoPad option when decrypting and remove the arbitrary padding bytes "by hand".

xmlenc#aes128-cbc: As for xmlenc#tripledes-cbc except use CipherAlgorithm.Aes128 option.

xmlenc#aes192-cbc: As for xmlenc#tripledes-cbc except use CipherAlgorithm.Aes192 option.

xmlenc#aes256-cbc: As for xmlenc#tripledes-cbc except use CipherAlgorithm.Aes256 option.

References

Contact

For more information, please send us a message.

This page last updated 7 December 2019

[Go to top]