Пример #1
0
        private static byte[] Decrypt(NppCryptCipherParams cipher, byte[] encryptedData, string password)
        {
            if (cipher.Encryption.Cipher != "rijndael")
            {
                throw new Exception($"Cipher algorithm \"{cipher.Encryption.Cipher}\" is not supported now. " +
                                    "Only \"rijndael\" algorithm might be used in the current version");
            }

            if (cipher.Encryption.Mode != CipherMode.CBC)
            {
                throw new Exception($"Cipher algorithm mode \"{cipher.Encryption.Mode}\" is not supported now. " +
                                    $"Only \"{nameof(CipherMode.CBC)}\" mode might be used in the current version");
            }


            if (cipher.Key.Algorithm != "scrypt")
            {
                throw new Exception($"Key hashing algorithm \"{cipher.Key.Algorithm}\" is not supported now. " +
                                    "Only \"scrypt\" algorithm might be used in the current version");
            }

            if (!cipher.Key.N.HasValue)
            {
                throw new Exception($"Parameter '{nameof(cipher.Key.N)}' of key hashing algorithm is not set");
            }
            if (!cipher.Key.R.HasValue)
            {
                throw new Exception($"Parameter '{nameof(cipher.Key.R)}' of key hashing algorithm is not set");
            }
            if (!cipher.Key.P.HasValue)
            {
                throw new Exception($"Parameter '{nameof(cipher.Key.P)}' of key hashing algorithm is not set");
            }
            if (cipher.Key.Salt == null)
            {
                throw new Exception($"Parameter '{nameof(cipher.Key.Salt)}' of key hashing algorithm is not set");
            }

            var key = ScryptEncoder.CryptoScrypt(Encoding.UTF8.GetBytes(password), cipher.Key.Salt,
                                                 cipher.Key.N.Value, cipher.Key.R.Value, cipher.Key.P.Value, cipher.Encryption.KeyLength ?? 32);

            using Rijndael rijAlg = Rijndael.Create();
            rijAlg.Key            = key;
            rijAlg.IV             = cipher.Iv.Value;
            rijAlg.Mode           = cipher.Encryption.Mode;

            using var ms = new MemoryStream();
            using var cs = new CryptoStream(ms, rijAlg.CreateDecryptor(), CryptoStreamMode.Write);
            cs.Write(encryptedData, 0, encryptedData.Length);
            cs.Close();
            var res = ms.ToArray();

            ms.Close();
            return(res);
        }
Пример #2
0
        private static NppCryptCipherParams ParseCipherParams(string nppCryptXml)
        {
            XmlDocument doc;

            try
            {
                doc = new XmlDocument();
                doc.LoadXml(nppCryptXml);
            }
            catch (Exception e)
            {
                throw new Exception("NppCrypt-header parsing exception", e);
            }

            var res = new NppCryptCipherParams
            {
                Encryption = new NppCryptEncryptionParams(),
                Key        = new NppCryptKeyParams(),
                Iv         = new NppCryptIvParams()
            };


            XmlNode getTag(XmlNode parent, string tagName)
            {
                using (var tagCollection = (parent as XmlElement)?.GetElementsByTagName(tagName))
                {
                    if (tagCollection?.Count != 1)
                    {
                        throw new Exception($"NppCrypt-header parsing exception. The \"<{tagName}>\" tag was not found " +
                                            "or is present in several instances");
                    }
                    return(tagCollection[0]);
                }
            }

            string getAttribute(XmlNode parent, string attributeName)
            {
                return(parent?.Attributes?[attributeName]?.Value);
            }

            byte[] parseBase64String(string str)
            {
                try
                {
                    return(Convert.FromBase64String(str));
                }
                catch
                {
                    return(null);
                }
            }

            CipherMode parseMode(string mode)
            {
                var m     = mode.Trim().ToUpperInvariant();
                var modes = Enum.GetValues(typeof(CipherMode)).Cast <CipherMode>().ToList();

                foreach (var cipherMode in modes)
                {
                    if (cipherMode.ToString().ToUpperInvariant() == m)
                    {
                        return(cipherMode);
                    }
                }
                throw new Exception($"Unknown cipher mode '{mode}'");
            }

            var encryptionTag = getTag(doc.DocumentElement, "encryption");

            res.Encryption.Cipher = getAttribute(encryptionTag, "cipher");
            if (int.TryParse(getAttribute(encryptionTag, "key-length"), out int keyLen))
            {
                res.Encryption.KeyLength = keyLen;
            }
            res.Encryption.Mode     = parseMode(getAttribute(encryptionTag, "mode"));
            res.Encryption.Encoding = getAttribute(encryptionTag, "encoding");

            var keyTag = getTag(doc.DocumentElement, "key");

            res.Key.Algorithm = getAttribute(keyTag, "algorithm");
            if (int.TryParse(getAttribute(keyTag, "N"), out int n))
            {
                res.Key.N = n;
            }
            if (int.TryParse(getAttribute(keyTag, "r"), out int r))
            {
                res.Key.R = r;
            }
            if (int.TryParse(getAttribute(keyTag, "p"), out int p))
            {
                res.Key.P = p;
            }
            res.Key.Salt = parseBase64String(getAttribute(keyTag, "salt"));

            var ivTag = getTag(doc.DocumentElement, "iv");

            res.Iv.Value  = parseBase64String(getAttribute(ivTag, "value"));
            res.Iv.Method = getAttribute(ivTag, "method");

            return(res);
        }