/* $Id: XmlEnc_DecryptXml.cs $ * Last updated: * $Date: 2020-12-07 03:17:00 $ * $Version: 1.0.0 $ */ /* Ref: * [Using CryptoSys PKI to encrypt and decrypt using XMLENC](https://www.cryptosys.net/pki/xmlenc-encrypt-decrypt.html) */ using System; using System.Text; using System.Diagnostics; using CryptoSysPKI; /******************************* LICENSE *********************************** * Copyright (C) 2020 David Ireland, DI Management Services Pty Limited. * All rights reserved. <www.di-mgt.com.au> <www.cryptosys.net> * The code in this module is licensed under the terms of the MIT license. * For a copy, see <http://opensource.org/licenses/MIT> **************************************************************************** */ namespace XmlEnc { class XmlEnc_DecryptXml { static void Main(string[] args) { string cipherValue; string s; Console.WriteLine("PKI Version={0}", General.Version()); ///////////////////////////////// // Decrypt block cipher CBC mode ///////////////////////////////// // FILE: encrypt-data-aes128-cbc.xml cipherValue = "QMpxhXq1DtBeyC9KfSaMQWrEtefe+e935gF/x62spvmL6IW0XeS0W4Kk31OgWzN0"; s = xmlenc_decrypt_cbc_data(cipherValue, "6162636465666768696A6B6C6D6E6F70", CipherAlgorithm.Aes128); Console.WriteLine("PT='{0}'", s); Debug.Assert(s.Length > 0); // Same again as a one-liner s = System.Text.Encoding.UTF8.GetString(Cipher.Decrypt( Cnv.FromBase64("QMpxhXq1DtBeyC9KfSaMQWrEtefe+e935gF/x62spvmL6IW0XeS0W4Kk31OgWzN0"), Cnv.FromHex("6162636465666768696A6B6C6D6E6F70"), null, CipherAlgorithm.Aes128, Mode.CBC, Padding.W3CPadding, Cipher.Opts.PrefixIV)); Console.WriteLine("PT='{0}'", s); Debug.Assert(s.Length > 0); // FILE: encrypt-data-aes192-cbc-kw-aes256.xml cipherValue = "50lv94d/DFJirJXYOUXaBlrO+7gIXpx8cqH+G2xvE4mueoIxmGs8RH7FBXwjuMgf"; s = xmlenc_decrypt_cbc_data(cipherValue, "F65CD2C48C1DA5565ED0AAB2D042713373C74C8E69332F2F", CipherAlgorithm.Aes192); Console.WriteLine("PT='{0}'", s); Debug.Assert(s.Length > 0); // FILE: encrypt-element-aes128-cbc-rsa-1_5.xml cipherValue = @"0wkECpTy60/FDwbVM4zgd9qJVjR4h0q4PLm5pyyIxAuhbEh0art03yEikmbWBt2H 7qOk2G9iufUdwwqNPuZV5Qw5Rg2FMvTx234lDERGn5p+hhjOTcss5JF9QDzgdiec KABX3vbCESi/f3uwQ8BYDT+6SnxTR+xtcNv5xhbUCIFk/TaenSWx6p6fntTwTl1e lpwnI0EtM1yf4a9tBiH9PNd36BUv2rvSi4cZvJqSB3ZKvGtuwwyRzOzlzl259d1u QuoYysTBEAHw/WIop8eAexU9PUv7UbTkQAQag1yStda+GepVdpXEpu4hcxXQcvfs 9AQgkAgh4JKrnY4Bhz2B/e4CHHfbEedDOi+FVYlZuLn0CzrKMnM+1nUmqxJVWHz7 hytidpuqNRw3gcMkYvgH6g=="; s = xmlenc_decrypt_cbc_data(cipherValue, "493185CE8177AC09C4DE6C7C75524B16", CipherAlgorithm.Aes128); Console.WriteLine("PT='{0}'", s); Debug.Assert(s.Length > 0); // FILE: encrypt-element-aes256-cbc-carried-kw-aes256.xml cipherValue = @"pdDtiyd7XQ/BFEEN0PMJuHnLUfCY+bJlsW+q04OiKSPnRd4/dS1tjaTfj5dPpGXe cY3fJvRsq9QP1CJiwyEC/EQ1zSLbzwOtZ+NtxtsFgYvPBJ9t86ZcXIjlErQ85z3L wnb8rSHpE9tu4tJ1rjgf2i6NCbdFnSMXLSDgLEs48+gkX0cJCmKxzRaSE4cV0OSl hBWND4EYzX1M679VlSYrI0de+lSPO3Vx+y/TuZ5Vo+uu9+YP+ce0LRkx2BicjjsP QO9sp+yjHPNDIV1Z7VHsDIWqqmBaNQo3GuzF5WzWgaXTKnPv/IgUQn+1t3EtgHyb JhnfR/1em16z/Zaf9Uy1Lfd//yfEJ9BCjqwe1UjwN6ytu1v2BHd+8bVjD2o+Dg8V 7ayOLlkWOTOLvtJMPOXPqw=="; s = xmlenc_decrypt_cbc_data(cipherValue, "41559545888C22BF367F7936E6A9FFB6D810B2AB42BF70220F2168DB9B503DC6", CipherAlgorithm.Aes256); Console.WriteLine("PT='{0}'", s); Debug.Assert(s.Length > 0); ///////////////////////////////////// // Decrypt block cipher AES-GCM mode ///////////////////////////////////// // FILE: encrypt-data-aes256-gcm.xml cipherValue = "AQIDBAUGBwgJCgsMqYHeLKkzx8/iBLZa8f+ZCMGHulqDdiELj+ghwhU1jg62WW0="; s = xmlenc_decrypt_gcm(cipherValue, "6162636465666768696A6B6C6D6E6F707172737475767778797A303132333435", AeadAlgorithm.Aes_256_Gcm); Console.WriteLine("PT='{0}'", s); Debug.Assert(s.Length > 0); // Same again as a one-liner s = System.Text.Encoding.UTF8.GetString(Cipher.DecryptAEAD( Cnv.FromBase64("AQIDBAUGBwgJCgsMqYHeLKkzx8/iBLZa8f+ZCMGHulqDdiELj+ghwhU1jg62WW0="), Cnv.FromHex("6162636465666768696A6B6C6D6E6F707172737475767778797A303132333435"), null, null, AeadAlgorithm.Aes_256_Gcm, Cipher.Opts.PrefixIV)); Console.WriteLine("PT='{0}'", s); Debug.Assert(s.Length > 0); // FILE: root-bob-oaep-gcm.xml cipherValue = "f4K4iAry8y7hz2mKl3Xpqnx5lVPTKkeKhM7PmGJITVE5pk4NZjFak1ZaKpgvoi3ooUP+sxUArXnNG/GrLYQ="; s = xmlenc_decrypt_gcm(cipherValue, "E2493529B46E23907FC77AB0C4DD74BE", AeadAlgorithm.Aes_128_Gcm); Console.WriteLine("PT='{0}'", s); Debug.Assert(s.Length > 0); // FILE: root-oaep-256-gcm-x2.xml cipherValue = "e2kl8SXHPvyy/qbzY2Rk46+6vWtTLgt4rSL+1IMkdJqBQvpqaMPFeKa4k4yxsa4XauwZZYdOIfwj13sFvMA="; s = xmlenc_decrypt_gcm(cipherValue, "F45F70F9645F73B3CB88DBD17EBA881B", AeadAlgorithm.Aes_128_Gcm); Console.WriteLine("PT='{0}'", s); Debug.Assert(s.Length > 0); ///////////////////////////////////// // Decrypt key wrap ///////////////////////////////////// // FILE: encrypt-data-aes192-cbc-kw-aes256.xml cipherValue = "4AAgyi3M7xNdBimbQZKdGJLn3/cS4Yv8QKuA01+gUnY="; s = xmlenc_decrypt_kw_keyhex(cipherValue, "6162636465666768696A6B6C6D6E6F707172737475767778797A303132333435", CipherAlgorithm.Aes256); Console.WriteLine("CEK=0x{0}", s); Debug.Assert(s.Length > 0); // Same again as a one-liner s = Cnv.ToHex(Cipher.KeyUnwrap( Cnv.FromBase64("4AAgyi3M7xNdBimbQZKdGJLn3/cS4Yv8QKuA01+gUnY="), Cnv.FromHex("6162636465666768696A6B6C6D6E6F707172737475767778797A303132333435"), CipherAlgorithm.Aes256)); Console.WriteLine("CEK=0x{0}", s); Debug.Assert(s.Length > 0); // FILE: encrypt-element-aes256-cbc-carried-kw-aes256.xml cipherValue = "bsL63D0hPN6EOyzdgfEmKsAAvoJiGM+Wp9a9KZM92IKdl7s3YSntRg=="; s = xmlenc_decrypt_kw_keyhex(cipherValue, "6162636465666768696A6B6C6D6E6F707172737475767778797A303132333435", CipherAlgorithm.Aes256); Console.WriteLine("CEK=0x{0}", s); Debug.Assert(s.Length > 0); ///////////////////////////////////// // Decrypt key rsa-1_5 ///////////////////////////////////// // FILE: encrypt-element-aes128-cbc-rsa-1_5.xml cipherValue = @"heZshNX5m7arS3OmR72+8WNCMMpznxE41dLWkgd6XJpzl+IN2xuijAf4YPEjjJmZ nt9PlO3/hiHl0Cvpg5vMR6AhvL49BvCz9JCeMG6x3MHBiKbRNhyEq2rX7o1GdJhC 5cm35Q/ZDKV9DHG8jWmPcOb8yKU9NYo2LJKDb3YHOJY="; s = xmlenc_decrypt_rsa_15_keyhex(cipherValue, "rsa-w3c.p8", ""); Console.WriteLine("CEK=0x{0}", s); Debug.Assert(s.Length > 0); // Same again as a one-liner s = Cnv.ToHex(Rsa.Decrypt(Cnv.FromBase64(@"heZshNX5m7arS3OmR72+8WNCMMpznxE41dLWkgd6XJpzl+IN2xuijAf4YPEjjJmZ nt9PlO3/hiHl0Cvpg5vMR6AhvL49BvCz9JCeMG6x3MHBiKbRNhyEq2rX7o1GdJhC 5cm35Q/ZDKV9DHG8jWmPcOb8yKU9NYo2LJKDb3YHOJY="), "rsa-w3c.p8", "")); Console.WriteLine("CEK=0x{0}", s); Debug.Assert(s.Length > 0); ///////////////////////////////////// // Decrypt key rsa-oaep ///////////////////////////////////// // FILE: root-bob-oaep-gcm.xml cipherValue = @"ne3BEmELlWOKCvevCnKmgZ9//JYNgSrtdighAztmUJAtuGCXWMqtfsSLccTUpEdm k4Vl+BampcxIiEvHduNkq1un9oV7ikyrTiT0A9jChlC8Tf8HU9XeU3I/I/5FqP8V IxWfnTLuvu/jp4lVyqoNmDtsooqlQtcaC0C7JRoc+bKeqMhzZxOgdUK3UM34aDDk HZHZSaMbWp8P59kJLUECMXTP+dW3q8MMucr7PEGhN5VGBKNH3/IlCvDvg3ROW/cY csCTh8Vve5h+eyiZUl2DcBITgj31qFkZ/QJtzoIG7PbkS5WU0NNtAguO6z7MbZlv PAOyQgvJpmSQqKUOrHro8g=="; s = xmlenc_decrypt_rsa_oaep_keyhex(cipherValue, "bob-smime.p8", "", Rsa.HashAlg.Sha256, Rsa.AdvOptions.Mgf1_Sha1); Console.WriteLine("CEK=0x{0}", s); Debug.Assert(s.Length > 0); // FILE: root-oaep-256-gcm-x2.xml cipherValue = @"qsIPCYkqgCSDv+xxNf0swqJiDZiVTsPrMdPcPFeaZW+yK3KqeHYHZubrTMV0Cj5b gezvKe/fq+OdIZVvxIDR/nJy0M/Jm6GiVnOmm2FzzP9YnsARubF2piwGGT5bo4a0 wkoH+bBBcZEMPG1LHWBUThBn+pz6ApV/ogLB4q5f5bkiqKSi4rZktT8fxxJJvqdg lrYmLNSM+QS51YP35xtBwMups8BTHNQ/n+YOoz0/X3xBMIgCc0K0W14LG9qgXsgR AVtxezJkiOq8q+jj12vNyBLqQoR3MnTaOM9kmHcwHFkCoG4HBgDTQJWOd2oIrHGi 2TfIvBsPHXk6STZKEj7u4A=="; s = xmlenc_decrypt_rsa_oaep_keyhex(cipherValue, "bob-smime.p8", "", Rsa.HashAlg.Sha256); Console.WriteLine("CEK=0x{0}", s); Debug.Assert(s.Length > 0); } /// <summary> /// Decrypt base64-encoded CipherValue using block cipher in CBC mode as per W3C XMLENC. /// </summary> /// <param name="cipherValue">Base64-encoded CipherValue</param> /// <param name="keyHex">Key in hex encoding of exact required length for algorithm (16|24|32 bytes)</param> /// <param name="cipherAlg">Block cipher algorithm</param> /// <returns>Decrypted plaintext as a Unicode string or the empty string on error.</returns> static string xmlenc_decrypt_cbc_data(string cipherValue, string keyHex, CipherAlgorithm cipherAlg) { byte[] pt = Cipher.Decrypt(Cnv.FromBase64(cipherValue), Cnv.FromHex(keyHex), null, cipherAlg, Mode.CBC, Padding.W3CPadding, Cipher.Opts.PrefixIV); return System.Text.Encoding.UTF8.GetString(pt); } /// <summary> /// Decrypt base64-encoded CipherValue using block cipher in AES-GCM mode as per W3C XMLENC. /// </summary> /// <param name="cipherValue">Base64-encoded CipherValue</param> /// <param name="keyHex">Key in hex encoding of exact required length for algorithm (16|24|32 bytes)</param> /// <param name="aeadAlg">Authenticated encryption algorithm</param> /// <returns>Decrypted plaintext as a Unicode string or the empty string on error.</returns> static string xmlenc_decrypt_gcm(string cipherValue, string keyHex, AeadAlgorithm aeadAlg) { byte[] pt = Cipher.DecryptAEAD(Cnv.FromBase64(cipherValue), Cnv.FromHex(keyHex), null, null, aeadAlg, Cipher.Opts.PrefixIV); return System.Text.Encoding.UTF8.GetString(pt); } /// <summary> /// Decrypt key wrap material. /// </summary> /// <param name="cipherValue">Base64-encoded CipherValue</param> /// <param name="kekHex">Key-encryption key (KEK) encoded in hex of exact required length for algorithm (16|24|32 bytes)</param> /// <param name="cipherAlg">Cipher algorithm</param> /// <returns>Key material encoded in hex.</returns> static string xmlenc_decrypt_kw_keyhex(string cipherValue, string kekHex, CipherAlgorithm cipherAlg) { byte[] key = Cipher.KeyUnwrap(Cnv.FromBase64(cipherValue), Cnv.FromHex(kekHex), cipherAlg); return Cnv.ToHex(key); } /// <summary> /// Decrypt key encrypted using RSA PKCS#1 v1.5 key transport algorithm. /// </summary> /// <param name="cipherValue">Base64-encoded CipherValue</param> /// <param name="rsaKeyFile">File containing RSA private key or a string containing the key in PEM format.</param> /// <param name="password">Password for key file or <c>""</c> if not required.</param> /// <returns>Key material encoded in hex.</returns> static string xmlenc_decrypt_rsa_15_keyhex(string cipherValue, string rsaKeyFile, string password = "") { byte[] key = Rsa.Decrypt(Cnv.FromBase64(cipherValue), rsaKeyFile, password); return Cnv.ToHex(key); } /// <summary> /// Decrypt key encrypted using RSA-OAEP key transport algorithm. /// </summary> /// <param name="cipherValue">Base64-encoded CipherValue</param> /// <param name="rsaKeyFile">File containing RSA private key or a string containing the key in PEM format.</param> /// <param name="password">Password for key file or <c>""</c> if not required.</param> /// <param name="hashAlg">Hash function for EME-OAEP encoding, otherwise ignored. [default = SHA-1]</param> /// <param name="advOpts"><c>Mgf1_Sha1</c> to force the MGF hash function to be SHA-1 [default = same as hash function set by <c>hashAlg</c>]</param> /// <returns>Key material encoded in hex.</returns> static string xmlenc_decrypt_rsa_oaep_keyhex(string cipherValue, string rsaKeyFile, string password = "", Rsa.HashAlg hashAlg = Rsa.HashAlg.Sha1, Rsa.AdvOptions advOpts = Rsa.AdvOptions.Default) { byte[] key = Rsa.Decrypt(Cnv.FromBase64(cipherValue), rsaKeyFile, password, Rsa.EME.OAEP, hashAlg, advOpts); return Cnv.ToHex(key); } } }