Esempio n. 1
0
        public List <KeyValuePair <GXPkcs8, GXx509Certificate> > GetClientKeys(string systemTitle)
        {
            byte[] st = null;
            if (!string.IsNullOrEmpty(systemTitle))
            {
                st = GXDLMSTranslator.HexToBytes(systemTitle);
            }
            List <KeyValuePair <GXPkcs8, GXx509Certificate> > list = new List <KeyValuePair <GXPkcs8, GXx509Certificate> >();

            if (st == null || st.Length == 8)
            {
                string subject = null;
                if (st != null)
                {
                    subject = GXAsn1Converter.SystemTitleToSubject(st);
                }
                GXPkcs8 k;
                foreach (GXx509Certificate cert in _certifications)
                {
                    if (subject == null || cert.Subject.Contains(subject))
                    {
                        if ((k = _privateKeys.Find(cert.PublicKey)) != null)
                        {
                            if ((cert.KeyUsage & KeyUsage.DigitalSignature) != 0)
                            {
                                list.Add(new KeyValuePair <GXPkcs8, GXx509Certificate>(k, cert));
                            }
                        }
                    }
                }
            }
            return(list);
        }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="certificateFolder"></param>
        /// <param name="title"></param>
        /// <param name="systemTitle">If system title is not null this certificate is selected.</param>
        public GXCertificateForm(IGXUpdater updater, string address, string certificateFolder, string title, byte[] systemTitle)
        {
            InitializeComponent();
            _updater = updater;
            _address = address;
            string st = null;

            if (systemTitle != null && systemTitle.Length == 8)
            {
                st = GXAsn1Converter.SystemTitleToSubject(systemTitle);
            }

            Certificates      = new GXx509CertificateCollection();
            CertificateFolder = certificateFolder;
            Title             = title;
            foreach (string p in Directory.GetFiles(CertificateFolder))
            {
                string ext = Path.GetExtension(p);
                if (string.Compare(ext, ".pem", true) == 0 || string.Compare(ext, ".cer", true) == 0)
                {
                    try
                    {
                        GXx509Certificate cert = GXx509Certificate.Load(p);
                        AddCertificate(cert, p, st);
                    }
                    catch (Exception ex)
                    {
                        ListViewItem li = new ListViewItem(new string[] { ex.Message, "", "", "", "", Path.GetFileNameWithoutExtension(p) });
                        li.Tag       = p;
                        li.BackColor = Color.Red;
                        CertificatesList.Items.Add(li);
                    }
                }
            }
        }
        /// <summary>
        /// Find certificate with given parameters.
        /// </summary>
        /// <param name="entity">Certificate entity.</param>
        /// <param name="type">Certificate type.</param>
        /// <param name="systemtitle">System title.</param>
        /// <returns></returns>
        public GXDLMSCertificateInfo Find(CertificateEntity entity, CertificateType type, byte[] systemtitle)
        {
            string subject = GXAsn1Converter.SystemTitleToSubject(systemtitle);

            foreach (GXDLMSCertificateInfo it in this)
            {
                if ((it.Entity == CertificateEntity.Server && entity == CertificateEntity.Server) ||
                    (it.Entity == CertificateEntity.Client && entity == CertificateEntity.Client) &&
                    it.Subject == subject)
                {
                    return(it);
                }
            }
            return(null);
        }
Esempio n. 4
0
        /// <summary>
        /// Generate Certificate Signing Request (CSR) from private key.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CSRBtn_Click(object sender, EventArgs e)
        {
            try
            {
                if (SystemTitleTb.Text == "")
                {
                    throw new Exception("Invalid system title.");
                }
                byte[] st = GXDLMSTranslator.HexToBytes(SystemTitleTb.Text);
                if (st.Length != 8)
                {
                    throw new Exception("Invalid system title.");
                }

                OpenFileDialog dlg = new OpenFileDialog();
                dlg.Multiselect = false;
                if (string.IsNullOrEmpty(_path))
                {
                    dlg.InitialDirectory = Directory.GetCurrentDirectory();
                }
                else
                {
                    System.IO.FileInfo fi = new System.IO.FileInfo(_path);
                    dlg.InitialDirectory = fi.DirectoryName;
                    dlg.FileName         = fi.Name;
                }
                dlg.Filter        = Properties.Resources.PemFilterTxt;
                dlg.DefaultExt    = ".pem";
                dlg.ValidateNames = true;
                if (dlg.ShowDialog(Parent) == DialogResult.OK)
                {
                    string  path = dlg.FileName;
                    GXPkcs8 pk   = GXPkcs8.Load(path);
                    KeyValuePair <GXPublicKey, GXPrivateKey> kp = new KeyValuePair <GXPublicKey, GXPrivateKey>(pk.PublicKey, pk.PrivateKey);
                    //Generate certificate request and ask new x509Certificate.
                    GXPkcs10 pkc10 = GXPkcs10.CreateCertificateSigningRequest(kp, GXAsn1Converter.SystemTitleToSubject(st));
                    Pkcs10Tb.Text = pkc10.ToPem();
                    Pkcs10Tb.AppendText(Environment.NewLine);
                    Pkcs10Tb.AppendText(pkc10.ToString());
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(Parent, ex.Message);
            }
        }
Esempio n. 5
0
        public GXKeyForm(IGXUpdater updater, string address, string keyFolder, string certificateFolder, string title, SecuritySuite securitySuite, byte[] systemTitle)
        {
            InitializeComponent();
            _updater           = updater;
            _address           = address;
            _certificateFolder = certificateFolder;
            _systemTitle       = systemTitle;
            privateKeys        = new GXPkcs8Collection();
            KeyFolder          = keyFolder;
            Title = title;

            foreach (string p in Directory.GetFiles(keyFolder))
            {
                string ext = Path.GetExtension(p);
                if (string.Compare(ext, ".pem", true) == 0 || string.Compare(ext, ".cer", true) == 0)
                {
                    try
                    {
                        GXPkcs8 cert = GXPkcs8.Load(p);
                        AddKey(cert, p);
                    }
                    catch (Exception)
                    {
                        Debug.WriteLine("Failed to open " + p);
                    }
                }
            }
            if (_systemTitle != null)
            {
                string path = Path.Combine(KeyFolder, "D" + GXDLMSTranslator.ToHex(_systemTitle, false)) + ".pem";
                //Generate private key for digital signature.
                GXPkcs8 digitalSignature = new GXPkcs8(GXEcdsa.GenerateKeyPair(securitySuite == SecuritySuite.Suite1 ? Ecc.P256 : Ecc.P384));
                digitalSignature.Save(path);
                AddKey(digitalSignature, path);
                path = Path.Combine(KeyFolder, "A" + GXDLMSTranslator.ToHex(_systemTitle, false)) + ".pem";
                //Generate private key for Key agreement.
                GXPkcs8 keyAgreement = new GXPkcs8(GXEcdsa.GenerateKeyPair(Ecc.P256));
                keyAgreement.Save(path);
                AddKey(keyAgreement, path);

                //Get CRS.
                KeyValuePair <GXPublicKey, GXPrivateKey> kp = new KeyValuePair <GXPublicKey, GXPrivateKey>(digitalSignature.PublicKey, digitalSignature.PrivateKey);
                //Generate certificate request and ask new x509Certificate.
                //Note! There is a limit how many request you can do in a day.
                List <GXCertificateRequest> certifications = new List <GXCertificateRequest>();
                GXCertificateRequest        it             = new GXCertificateRequest();
                it.Certificate     = GXPkcs10.CreateCertificateSigningRequest(kp, GXAsn1Converter.SystemTitleToSubject(_systemTitle));
                it.CertificateType = CertificateType.DigitalSignature;
                certifications.Add(it);
                it                 = new GXCertificateRequest();
                it.Certificate     = GXPkcs10.CreateCertificateSigningRequest(kp, GXAsn1Converter.SystemTitleToSubject(_systemTitle));
                it.CertificateType = CertificateType.KeyAgreement;
                certifications.Add(it);
                GXx509Certificate[] certificates = GXPkcs10.GetCertificate(address, certifications);
                foreach (GXx509Certificate cert in certificates)
                {
                    if (cert.KeyUsage == KeyUsage.DigitalSignature)
                    {
                        path = "D" + GXDLMSTranslator.ToHex(_systemTitle, false);
                    }
                    else if (cert.KeyUsage == KeyUsage.KeyAgreement)
                    {
                        path = "A" + GXDLMSTranslator.ToHex(_systemTitle, false);
                    }
                    else if (cert.KeyUsage == (KeyUsage.KeyAgreement | KeyUsage.DigitalSignature))
                    {
                        path = "T" + GXDLMSTranslator.ToHex(_systemTitle, false);
                    }
                    else
                    {
                        path = "O" + GXDLMSTranslator.ToHex(_systemTitle, false);
                    }
                    path = Path.Combine(_certificateFolder, path) + ".pem";
                    cert.Save(path);
                }
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Get certificate for the private key.
        /// </summary>
        private void GetCertificateMnu_Click(object sender, EventArgs e)
        {
            try
            {
                ListViewItem it = KeyList.SelectedItems[0];
                GXCertificateSigningRequestDlg dlg = new GXCertificateSigningRequestDlg(SystemTitle);
                if (dlg.ShowDialog(Parent) == DialogResult.OK)
                {
                    SystemTitle = dlg.SystemTitle;
                    GXPkcs8 pk = GXPkcs8.Load((string)it.Tag);
                    KeyValuePair <GXPublicKey, GXPrivateKey> kp = new KeyValuePair <GXPublicKey, GXPrivateKey>(pk.PublicKey, pk.PrivateKey);
                    List <GXCertificateRequest> certifications  = new List <GXCertificateRequest>();
                    GXCertificateRequest        it2             = new GXCertificateRequest();
                    it2.CertificateType  = dlg.CertificateType;
                    it2.ExtendedKeyUsage = dlg.ExtendedKeyUsage;
                    //Generate certificate request and ask new x509Certificate.
                    it2.Certificate = GXPkcs10.CreateCertificateSigningRequest(kp, GXAsn1Converter.SystemTitleToSubject(SystemTitle));
                    certifications.Add(it2);
                    //Note! There is a limit how many request you can do in a day.
                    GXx509Certificate[] certificates = GXPkcs10.GetCertificate(_address, certifications);
                    foreach (GXx509Certificate cert in certificates)
                    {
                        if (cert.KeyUsage == KeyUsage.DigitalSignature)
                        {
                            _path = "D" + Path.GetFileName((string)it.Tag);
                        }
                        else if (cert.KeyUsage == KeyUsage.KeyAgreement)
                        {
                            _path = "A" + Path.GetFileName((string)it.Tag);
                        }
                        else if (cert.KeyUsage == (KeyUsage.KeyAgreement | KeyUsage.DigitalSignature))
                        {
                            //TLS.
                            _path = "T" + Path.GetFileName((string)it.Tag);
                        }
                        else
                        {
                            //Other.
                            _path = "O" + Path.GetFileName((string)it.Tag);
                        }

                        if (File.Exists(_path))
                        {
                            if (cert.KeyUsage == KeyUsage.DigitalSignature)
                            {
                                _path = "D" + GXDLMSTranslator.ToHex(SystemTitle, false);
                            }
                            else if (cert.KeyUsage == KeyUsage.KeyAgreement)
                            {
                                _path = "A" + GXDLMSTranslator.ToHex(SystemTitle, false);
                            }
                            else if (cert.KeyUsage == (KeyUsage.KeyAgreement | KeyUsage.DigitalSignature))
                            {
                                //TLS.
                                _path = "T" + GXDLMSTranslator.ToHex(SystemTitle, false);
                            }
                            else
                            {
                                //Other.
                                _path = "O" + GXDLMSTranslator.ToHex(SystemTitle, false);
                            }
                            _path += ".pem";
                        }
                        _path = Path.Combine(_certificateFolder, _path);
                        cert.Save(_path);
                    }
                    _updater.UpdateUI();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(Parent, ex.Message);
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Decrypt data.
        /// </summary>
        /// <param name="p">Decryption parameters</param>
        /// <returns>Decrypted data.</returns>
        public static byte[] DecryptAesGcm(AesGcmParameter p, GXByteBuffer data)
        {
            if (data == null || data.Size < 2)
            {
                throw new ArgumentOutOfRangeException("cryptedData");
            }
            byte[]  tmp;
            int     len;
            Command cmd = (Command)data.GetUInt8();

            switch (cmd)
            {
            case Command.GeneralGloCiphering:
            case Command.GeneralDedCiphering:
                len = GXCommon.GetObjectCount(data);
                if (len != 0)
                {
                    p.SystemTitle = new byte[len];
                    data.Get(p.SystemTitle);
                    if (p.Xml != null && p.Xml.Comments)
                    {
                        p.Xml.AppendComment(GXCommon.SystemTitleToString(Standard.DLMS, p.SystemTitle, true));
                    }
                }
                if (p.SystemTitle == null || p.SystemTitle.Length != 8)
                {
                    if (p.Xml == null)
                    {
                        throw new ArgumentNullException("Invalid sender system title.");
                    }
                    else
                    {
                        p.Xml.AppendComment("Invalid sender system title.");
                    }
                }
                break;

            case Command.GeneralCiphering:
            case Command.GloInitiateRequest:
            case Command.GloInitiateResponse:
            case Command.GloReadRequest:
            case Command.GloReadResponse:
            case Command.GloWriteRequest:
            case Command.GloWriteResponse:
            case Command.GloGetRequest:
            case Command.GloGetResponse:
            case Command.GloSetRequest:
            case Command.GloSetResponse:
            case Command.GloMethodRequest:
            case Command.GloMethodResponse:
            case Command.GloEventNotification:
            case Command.DedInitiateRequest:
            case Command.DedInitiateResponse:
            case Command.DedGetRequest:
            case Command.DedGetResponse:
            case Command.DedSetRequest:
            case Command.DedSetResponse:
            case Command.DedMethodRequest:
            case Command.DedMethodResponse:
            case Command.DedEventNotification:
            case Command.DedReadRequest:
            case Command.DedReadResponse:
            case Command.DedWriteRequest:
            case Command.DedWriteResponse:
            case Command.GloConfirmedServiceError:
            case Command.DedConfirmedServiceError:
                break;

            default:
                throw new ArgumentOutOfRangeException("cryptedData");
            }
            int          value         = 0;
            GXPrivateKey key           = null;
            GXPublicKey  pub           = null;
            GXByteBuffer transactionId = null;

            if (cmd == Command.GeneralCiphering)
            {
                transactionId = new GXByteBuffer();
                len           = GXCommon.GetObjectCount(data);
                GXCommon.SetObjectCount(len, transactionId);
                transactionId.Set(data, len);
                p.TransactionId = transactionId.GetUInt64(1);
                len             = GXCommon.GetObjectCount(data);
                if (len != 0)
                {
                    tmp = new byte[len];
                    data.Get(tmp);
                    p.SystemTitle = tmp;
                }
                if (p.SystemTitle == null || p.SystemTitle.Length != 8)
                {
                    if (p.Xml == null)
                    {
                        throw new ArgumentNullException("Invalid sender system title.");
                    }
                    else
                    {
                        p.Xml.AppendComment("Invalid sender system title.");
                    }
                }
                len = GXCommon.GetObjectCount(data);
                tmp = new byte[len];
                data.Get(tmp);
                p.RecipientSystemTitle = tmp;
                // Get date time.
                len = GXCommon.GetObjectCount(data);
                if (len != 0)
                {
                    tmp = new byte[len];
                    data.Get(tmp);
                    p.DateTime = tmp;
                }
                // other-information
                len = data.GetUInt8();
                if (len != 0)
                {
                    tmp = new byte[len];
                    data.Get(tmp);
                    p.OtherInformation = tmp;
                }
                // KeyInfo OPTIONAL
                len = data.GetUInt8();
                // AgreedKey CHOICE tag.
                data.GetUInt8();
                // key-parameters
                len             = data.GetUInt8();
                value           = data.GetUInt8();
                p.KeyParameters = value;
                if (value == (int)KeyAgreementScheme.OnePassDiffieHellman)
                {
                    // key-ciphered-data
                    len = GXCommon.GetObjectCount(data);
                    GXByteBuffer bb = new GXByteBuffer();
                    bb.Set(data, len);
                    if (p.Xml != null)
                    {
                        p.KeyCipheredData = bb.Array();
                        //Find key agreement key using subject.
                        string subject = GXAsn1Converter.SystemTitleToSubject(p.SystemTitle);
                        foreach (KeyValuePair <GXPkcs8, GXx509Certificate> it in p.Settings.Keys)
                        {
                            if (it.Key != null && it.Value.KeyUsage == ASN.Enums.KeyUsage.KeyAgreement && it.Value.Subject.Contains(subject))
                            {
                                key = it.Key.PrivateKey;
                                //Get recipient Ephemeral public key.
                                subject = GXAsn1Converter.SystemTitleToSubject(p.RecipientSystemTitle);
                                foreach (KeyValuePair <GXPkcs8, GXx509Certificate> it2 in p.Settings.Keys)
                                {
                                    if (it2.Value != null && it2.Value.KeyUsage == ASN.Enums.KeyUsage.KeyAgreement && it2.Value.Subject.Contains(subject))
                                    {
                                        pub = it2.Value.PublicKey;
                                        break;
                                    }
                                }
                                break;
                            }
                        }
                        if (key == null)
                        {
                            //Find key agreement key using subject.
                            subject = GXAsn1Converter.SystemTitleToSubject(p.RecipientSystemTitle);
                            foreach (KeyValuePair <GXPkcs8, GXx509Certificate> it in p.Settings.Keys)
                            {
                                if (it.Key != null && it.Value.KeyUsage == ASN.Enums.KeyUsage.KeyAgreement && it.Value.Subject.Contains(subject))
                                {
                                    key = it.Key.PrivateKey;
                                    break;
                                }
                            }
                        }
                    }
                    else
                    {
                        key = p.Settings.Cipher.KeyAgreementKeyPair.Key;
                    }
                    if (key != null && pub == null)
                    {
                        //Get Ephemeral public key.
                        int keySize = len / 2;
                        pub = GXPublicKey.FromRawBytes(bb.SubArray(0, keySize));
                    }
                }
                else if (value == (int)KeyAgreementScheme.StaticUnifiedModel)
                {
                    len = GXCommon.GetObjectCount(data);
                    if (len != 0)
                    {
                        throw new ArgumentException("Invalid key parameters");
                    }
                    if (p.Xml != null)
                    {
                        //Find key agreement key using subject.
                        string subject = GXAsn1Converter.SystemTitleToSubject(p.RecipientSystemTitle);
                        foreach (KeyValuePair <GXPkcs8, GXx509Certificate> it in p.Settings.Keys)
                        {
                            if (it.Value.KeyUsage == ASN.Enums.KeyUsage.KeyAgreement && it.Value.Subject.Contains(subject))
                            {
                                key = it.Key.PrivateKey;
                                break;
                            }
                        }
                        if (key != null)
                        {
                            //Find key agreement key using subject.
                            subject = GXAsn1Converter.SystemTitleToSubject(p.Settings.SourceSystemTitle);
                            foreach (KeyValuePair <GXPkcs8, GXx509Certificate> it in p.Settings.Keys)
                            {
                                if (it.Value.KeyUsage == ASN.Enums.KeyUsage.KeyAgreement && it.Value.Subject.Contains(subject))
                                {
                                    pub = it.Value.PublicKey;
                                    break;
                                }
                            }
                        }
                    }
                    else
                    {
                        key = p.Settings.Cipher.KeyAgreementKeyPair.Key;
                        pub = p.Settings.Cipher.KeyAgreementKeyPair.Value;
                    }
                }
                else
                {
                    throw new ArgumentException("key-parameters");
                }
            }
            len = GXCommon.GetObjectCount(data);
            if (len > data.Available)
            {
                throw new Exception("Not enought data.");
            }
            p.CipheredContent = data.Remaining();
            byte sc = data.GetUInt8();

            p.SecuritySuite = (SecuritySuite)(sc & 0x3);
            p.Security      = (Security)(sc & 0x30);
            if ((sc & 0x80) != 0)
            {
                System.Diagnostics.Debug.WriteLine("Compression is used.");
            }
            if ((sc & 0x40) != 0)
            {
                System.Diagnostics.Debug.WriteLine("Error: Key_Set is used.");
            }
            if ((sc & 0x20) != 0)
            {
                System.Diagnostics.Debug.WriteLine("Encryption is applied.");
            }
            if (key != null)
            {
                if (value == (int)KeyAgreementScheme.OnePassDiffieHellman)
                {
                    GXEcdsa c = new GXEcdsa(key);
                    //Get Ephemeral signing key and verify it.
                    byte[] z = c.GenerateSecret(pub);
                    System.Diagnostics.Debug.WriteLine("Originator ephemeral public key: " + pub.ToHex());
                    System.Diagnostics.Debug.WriteLine("Recipient private agreement key: " + key.ToHex());
                    System.Diagnostics.Debug.WriteLine("Shared secret:" + GXCommon.ToHex(z, true));

                    GXByteBuffer kdf = new GXByteBuffer();
                    kdf.Set(GXSecure.GenerateKDF(p.SecuritySuite, z,
                                                 p.SecuritySuite == SecuritySuite.Ecdsa256 ? AlgorithmId.AesGcm128 : AlgorithmId.AesGcm256,
                                                 p.SystemTitle,
                                                 p.RecipientSystemTitle,
                                                 null, null));
                    System.Diagnostics.Debug.WriteLine("KDF:" + kdf.ToString());
                    p.BlockCipherKey = kdf.SubArray(0, 16);
                }
                else if (value == (int)KeyAgreementScheme.StaticUnifiedModel)
                {
                    GXEcdsa c = new GXEcdsa(key);
                    byte[]  z = c.GenerateSecret(pub);
                    System.Diagnostics.Debug.WriteLine("Shared secret:" + GXCommon.ToHex(z, true));
                    GXByteBuffer kdf = new GXByteBuffer();
                    kdf.Set(GXSecure.GenerateKDF(p.SecuritySuite, z,
                                                 p.SecuritySuite == SecuritySuite.Ecdsa256 ? AlgorithmId.AesGcm128 : AlgorithmId.AesGcm256,
                                                 p.SystemTitle,
                                                 transactionId.Array(),
                                                 p.RecipientSystemTitle,
                                                 null));
                    System.Diagnostics.Debug.WriteLine("KDF:" + kdf.ToString());
                    p.BlockCipherKey = kdf.SubArray(0, 16);
                }
                else
                {
                    throw new ArgumentOutOfRangeException("Invalid Key-id value.");
                }
            }
            UInt32 invocationCounter = data.GetUInt32();

            p.InvocationCounter = invocationCounter;
            System.Diagnostics.Debug.WriteLine("Decrypt settings: " + p.ToString());
            System.Diagnostics.Debug.WriteLine("Encrypted: " + GXCommon.ToHex(data.Data,
                                                                              false, data.Position, data.Size - data.Position));
            byte[] tag = new byte[12];
            byte[] encryptedData;
            int    length;

            if (p.Security == Security.Authentication)
            {
                length        = data.Size - data.Position - 12;
                encryptedData = new byte[length];
                data.Get(encryptedData);
                data.Get(tag);
                // Check tag.
                EncryptAesGcm(p, encryptedData);
                if (!GXDLMSChipperingStream.TagsEquals(tag, p.CountTag))
                {
                    if (p.Xml == null)
                    {
                        throw new GXDLMSException("Decrypt failed. Invalid tag.");
                    }
                    else
                    {
                        p.Xml.AppendComment("Decrypt failed. Invalid tag.");
                    }
                }
                return(encryptedData);
            }
            byte[] ciphertext = null;
            if (p.Security == Security.Encryption)
            {
                length     = data.Size - data.Position;
                ciphertext = new byte[length];
                data.Get(ciphertext);
            }
            else if (p.Security == Security.AuthenticationEncryption)
            {
                length     = data.Size - data.Position - 12;
                ciphertext = new byte[length];
                data.Get(ciphertext);
                data.Get(tag);
            }
            byte[] aad = GetAuthenticatedData(p, ciphertext),
            iv = GetNonse(invocationCounter, p.SystemTitle);
            GXDLMSChipperingStream gcm = new GXDLMSChipperingStream(p.Security, true,
                                                                    p.BlockCipherKey, aad, iv, tag);

            gcm.Write(ciphertext);
            byte[] decrypted = gcm.FlushFinalBlock();
            System.Diagnostics.Debug.WriteLine("Decrypted: " + GXCommon.ToHex(decrypted, true));
            if (p.Security != Security.Encryption)
            {
                if (!GXCommon.Compare(gcm.GetTag(), tag))
                {
                    if (p.Xml == null)
                    {
                        throw new Exception("Decrypt failed. Invalid authentication tag.");
                    }
                    p.Xml.AppendComment("Decrypt failed. Invalid authentication tag.");
                }
            }
            return(decrypted);
        }