예제 #1
0
        public static string RandomSeed(int len)
        {
            byte[] seed = new byte[len];
            RNG.GetBytes(seed);

            return(EncodingConverter.ByteToHexBitFiddleLowercase(seed));
        }
예제 #2
0
        public static (byte[] pw, byte[] mk, string reqpw) CreateAuthData001(StandardNoteAPI.APIResultAuthParams apiparams, string mail, string uip)
        {
            if (apiparams.pw_func != StandardNoteAPI.PasswordFunc.pbkdf2)
            {
                throw new Exception("Unsupported pw_func: " + apiparams.pw_func);
            }

            byte[] bytes;

            if (apiparams.pw_alg == StandardNoteAPI.PasswordAlg.sha512)
            {
                bytes = PBKDF2.GenerateDerivedKey(apiparams.pw_key_size / 8, Encoding.UTF8.GetBytes(uip), Encoding.UTF8.GetBytes(apiparams.pw_salt), apiparams.pw_cost, PBKDF2.HMACType.SHA512);
            }
            else if (apiparams.pw_alg == StandardNoteAPI.PasswordAlg.sha512)
            {
                bytes = PBKDF2.GenerateDerivedKey(apiparams.pw_key_size / 8, Encoding.UTF8.GetBytes(uip), Encoding.UTF8.GetBytes(apiparams.pw_salt), apiparams.pw_cost, PBKDF2.HMACType.SHA512);
            }
            else
            {
                throw new Exception("Unknown pw_alg: " + apiparams.pw_alg);
            }

            var pw = bytes.Take(bytes.Length / 2).ToArray();
            var mk = bytes.Skip(bytes.Length / 2).ToArray();

            var reqpw = EncodingConverter.ByteToHexBitFiddleLowercase(pw);

            return(pw, mk, reqpw);
        }
예제 #3
0
        private static string DecryptContent004(string encContent, string encItemKey, Guid?itemsKeyID, StandardNoteData dat)
        {
            StandardNoteAPI.Logger.TraceExt(StandardNotePlugin.Name, "Decrypt content with schema [002]",
                                            ("encContent", encContent),
                                            ("encItemKey", encItemKey),
                                            ("itemsKeyID", itemsKeyID?.ToString() ?? "NULL"));

            var keyOuter = dat.SessionData.RootKey_MasterKey;

            if (itemsKeyID != null)
            {
                var itemskey = dat.ItemsKeys.FirstOrDefault(p => p.UUID == itemsKeyID);
                if (itemskey == null)
                {
                    throw new StandardNoteAPIException($"Could not decrypt item (Key {itemsKeyID} not found)");
                }

                StandardNoteAPI.Logger.TraceExt(StandardNotePlugin.Name, $"Found itemskey: {itemskey.UUID}",
                                                ("itemskey.IsDefault", itemskey.IsDefault.ToString()),
                                                ("itemskey.Version", itemskey.Version),
                                                ("itemskey.Key", EncodingConverter.ByteToHexBitFiddleLowercase(itemskey.Key)));

                keyOuter = itemskey.Key;
            }

            var keyInner = Decrypt004(encItemKey, keyOuter);

            return(Decrypt004(encContent, EncodingConverter.StringToByteArrayCaseInsensitive(keyInner)));
        }
예제 #4
0
 public static string SHA256Hex(string data)
 {
     using (var sha = SHA256.Create())
     {
         var hash = sha.ComputeHash(Encoding.UTF8.GetBytes(data));
         return(EncodingConverter.ByteToHexBitFiddleLowercase(hash));
     }
 }
예제 #5
0
        private static string DecryptContent001(string encContent, string encItemKey, string authHash, StandardNoteData dat)
        {
            StandardNoteAPI.Logger.TraceExt(StandardNotePlugin.Name, "Decrypt content with schema [001]",
                                            ("encContent", encContent),
                                            ("encItemKey", encItemKey),
                                            ("authHash", authHash));

            byte[] masterkey;

            if (dat.SessionData.Version == "001" || dat.SessionData.Version == "002" || dat.SessionData.Version == "003")
            {
                masterkey = dat.SessionData.RootKey_MasterKey;

                StandardNoteAPI.Logger.Trace(StandardNotePlugin.Name, "Use masterkey from session");
            }
            else
            {
                var itemskey = dat.ItemsKeys.FirstOrDefault(p => p.Version == "001");
                if (itemskey == null)
                {
                    throw new StandardNoteAPIException($"Could not decrypt item (Key for 002 not found)");
                }

                StandardNoteAPI.Logger.TraceExt(StandardNotePlugin.Name, $"Found itemskey: {itemskey.UUID}",
                                                ("itemskey.IsDefault", itemskey.IsDefault.ToString()),
                                                ("itemskey.Version", itemskey.Version),
                                                ("itemskey.Key", EncodingConverter.ByteToHexBitFiddleLowercase(itemskey.Key)),
                                                ("itemskey.AuthKey", EncodingConverter.ByteToHexBitFiddleLowercase(itemskey.AuthKey)));

                masterkey = itemskey.Key;
            }

            var itemKey = EncodingConverter.StringToByteArrayCaseInsensitive(Encoding.ASCII.GetString(AESEncryption.DecryptCBC256(Convert.FromBase64String(encItemKey), masterkey, new byte[16])));

            var ek = itemKey.Take(itemKey.Length / 2).ToArray();
            var ak = itemKey.Skip(itemKey.Length / 2).ToArray();

            var realHash = EncodingConverter.ByteToHexBitFiddleLowercase(AuthSHA256(Encoding.UTF8.GetBytes(encContent), ak));

            if (authHash == null)
            {
                throw new ArgumentNullException(nameof(authHash));
            }
            if (realHash.ToLower() != authHash.ToLower())
            {
                throw new StandardNoteAPIException("Decrypting content failed - hash mismatch");
            }

            var c = AESEncryption.DecryptCBC256(Convert.FromBase64String(encContent.Substring(3)), ek, null);

            return(Encoding.UTF8.GetString(c));
        }
예제 #6
0
        public static (byte[] mk, byte[] sp, string reqpw) CreateAuthData004(StandardNoteAPI.APIResultAuthParams apiparams, string mail, string uip)
        {
            var salt = StandardNoteCrypt.SHA256Bytes(string.Join(":", apiparams.identifier, apiparams.pw_nonce)).Take(128 / 8).ToArray();

            var derivedKey = ANCrypt.Argon2(Encoding.UTF8.GetBytes(uip), salt, 5, 64 * 1024, 64);

            var masterKey      = derivedKey.Skip(00).Take(32).ToArray();
            var serverPassword = derivedKey.Skip(32).Take(32).ToArray();

            var requestPassword = EncodingConverter.ByteToHexBitFiddleLowercase(serverPassword);

            return(masterKey, serverPassword, requestPassword);
        }
예제 #7
0
        private static string Encrypt003(string string_to_encrypt, Guid uuid, byte[] encryption_key, byte[] auth_key)
        {
            byte[] IV = new byte[128 / 8];
            RNG.GetBytes(IV);

            var ciphertext = AESEncryption.EncryptCBC256(Encoding.UTF8.GetBytes(string_to_encrypt), encryption_key, IV);

            var string_to_auth = $"003:{uuid:D}:{EncodingConverter.ByteToHexBitFiddleLowercase(IV)}:{Convert.ToBase64String(ciphertext)}";

            var auth_hash = EncodingConverter.ByteToHexBitFiddleLowercase(AuthSHA256(Encoding.UTF8.GetBytes(string_to_auth), auth_key));

            return($"003:{auth_hash}:{uuid:D}:{EncodingConverter.ByteToHexBitFiddleLowercase(IV)}:{Convert.ToBase64String(ciphertext)}");
        }
예제 #8
0
        private static string DecryptContent001(string encContent, string encItemKey, string authHash, byte[] masterkey)
        {
            var itemKey = EncodingConverter.StringToByteArrayCaseInsensitive(Encoding.ASCII.GetString(AESEncryption.DecryptCBC256(Convert.FromBase64String(encItemKey), masterkey, new byte[16])));

            var ek = itemKey.Take(itemKey.Length / 2).ToArray();
            var ak = itemKey.Skip(itemKey.Length / 2).ToArray();

            var realHash = EncodingConverter.ByteToHexBitFiddleLowercase(AuthSHA256(Encoding.UTF8.GetBytes(encContent), ak));

            if (realHash.ToLower() != authHash.ToLower())
            {
                throw new StandardNoteAPIException("Decrypting content failed - hash mismatch");
            }

            var c = AESEncryption.DecryptCBC256(Convert.FromBase64String(encContent.Substring(3)), ek, null);

            return(Encoding.UTF8.GetString(c));
        }
예제 #9
0
        private static EncryptResult EncryptContent003(string rawContent, Guid uuid, byte[] masterMK, byte[] masterAK)
        {
            byte[] itemKey = new byte[512 / 8];
            RNG.GetBytes(itemKey);

            var item_ek = itemKey.Take(itemKey.Length / 2).ToArray();
            var item_ak = itemKey.Skip(itemKey.Length / 2).ToArray();

            var encContent = Encrypt003(rawContent, uuid, item_ek, item_ak);

            var encItemKey = Encrypt003(EncodingConverter.ByteToHexBitFiddleLowercase(itemKey), uuid, masterMK, masterAK);

            return(new EncryptResult
            {
                enc_item_key = encItemKey,
                enc_content = encContent,
                auth_hash = null,
            });
        }
예제 #10
0
        private static string DecryptContent003(string encContent, string encItemKey, StandardNoteData dat)
        {
            StandardNoteAPI.Logger.TraceExt(StandardNotePlugin.Name, "Decrypt content with schema [002]",
                                            ("encContent", encContent),
                                            ("encItemKey", encItemKey));

            byte[] masterMK;
            byte[] masterAK;

            if (dat.SessionData.Version == "001" || dat.SessionData.Version == "002" || dat.SessionData.Version == "003")
            {
                masterMK = dat.SessionData.RootKey_MasterKey;
                masterAK = dat.SessionData.RootKey_MasterAuthKey;

                StandardNoteAPI.Logger.Trace(StandardNotePlugin.Name, "Use key/authkey from session");
            }
            else
            {
                var itemskey = dat.ItemsKeys.FirstOrDefault(p => p.Version == "003");
                if (itemskey == null)
                {
                    throw new StandardNoteAPIException($"Could not decrypt item (Key for 002 not found)");
                }

                StandardNoteAPI.Logger.TraceExt(StandardNotePlugin.Name, $"Found itemskey: {itemskey.UUID}",
                                                ("itemskey.IsDefault", itemskey.IsDefault.ToString()),
                                                ("itemskey.Version", itemskey.Version),
                                                ("itemskey.Key", EncodingConverter.ByteToHexBitFiddleLowercase(itemskey.Key)),
                                                ("itemskey.AuthKey", EncodingConverter.ByteToHexBitFiddleLowercase(itemskey.AuthKey)));

                masterMK = itemskey.Key;
                masterAK = itemskey.AuthKey;
            }

            var item_key = Decrypt003(encItemKey, masterMK, masterAK);

            StandardNoteAPI.Logger.Trace(StandardNotePlugin.Name, "item_key decrypted", $"item_key := '{item_key}'");

            var item_ek = item_key.Substring(0, item_key.Length / 2);
            var item_ak = item_key.Substring(item_key.Length / 2, item_key.Length / 2);

            return(Decrypt003(encContent, EncodingConverter.StringToByteArrayCaseInsensitive(item_ek), EncodingConverter.StringToByteArrayCaseInsensitive(item_ak)));
        }
예제 #11
0
        private static EncryptResult EncryptContent001(string content, byte[] mk)
        {
            byte[] itemKey = new byte[512 / 8];

            RNG.GetBytes(itemKey);

            var ek = itemKey.Take(itemKey.Length / 2).ToArray();
            var ak = itemKey.Skip(itemKey.Length / 2).ToArray();

            string encContent = "001" + Convert.ToBase64String(AESEncryption.EncryptCBC256(Encoding.UTF8.GetBytes(content), ek, null));

            var authHash = EncodingConverter.ByteToHexBitFiddleLowercase(AuthSHA256(Encoding.UTF8.GetBytes(encContent), ak));

            var encItemKey = Convert.ToBase64String(AESEncryption.EncryptCBC256(Encoding.UTF8.GetBytes(EncodingConverter.ByteToHexBitFiddleLowercase(itemKey)), mk, null));

            return(new EncryptResult
            {
                enc_item_key = encItemKey,
                enc_content = encContent,
                auth_hash = authHash,
            });
        }
예제 #12
0
        private static string Decrypt003(string string_to_decrypt, byte[] encryption_key, byte[] auth_key)
        {
            var components = string_to_decrypt.Split(':');
            var version    = components[0];
            var auth_hash  = components[1];
            var uuid       = components[2];
            var IV         = components[3];
            var ciphertext = components[4];

            if (auth_key != null && auth_key.Length > 0)
            {
                var string_to_auth  = $"{version}:{uuid}:{IV}:{ciphertext}";
                var local_auth_hash = EncodingConverter.ByteToHexBitFiddleLowercase(AuthSHA256(Encoding.UTF8.GetBytes(string_to_auth), auth_key));
                if (local_auth_hash.ToUpper() != auth_hash.ToUpper())
                {
                    throw new Exception("Item auth-hash mismatch");
                }
            }

            var result = AESEncryption.DecryptCBC256(Convert.FromBase64String(ciphertext), encryption_key, EncodingConverter.StringToByteArrayCaseInsensitive(IV));

            return(Encoding.UTF8.GetString(result));
        }
예제 #13
0
        private static string Decrypt003(string string_to_decrypt, byte[] encryption_key, byte[] auth_key)
        {
            var components = string_to_decrypt.Split(':');
            var version    = components[0];
            var auth_hash  = components[1];
            var uuid       = components[2];
            var IV         = components[3];
            var ciphertext = components[4];

            if (auth_key != null && auth_key.Length > 0)
            {
                var string_to_auth  = $"{version}:{uuid}:{IV}:{ciphertext}";
                var local_auth_hash = EncodingConverter.ByteToHexBitFiddleLowercase(AuthSHA256(Encoding.UTF8.GetBytes(string_to_auth), auth_key));

                if (local_auth_hash.ToUpper() != auth_hash.ToUpper())
                {
                    StandardNoteAPI.Logger.Warn(StandardNotePlugin.Name, "AuthHash verification failed",
                                                $"local_auth_hash := '{local_auth_hash}'\nauth_hash := '{auth_hash}'");

                    throw new Exception("Item auth-hash mismatch");
                }
                else
                {
                    StandardNoteAPI.Logger.TraceExt(StandardNotePlugin.Name, "AuthHash verified",
                                                    ("local_auth_hash", local_auth_hash),
                                                    ("auth_hash", auth_hash));
                }
            }
            else
            {
                StandardNoteAPI.Logger.Warn(StandardNotePlugin.Name, "AuthHash verification skipped (no auth_key)");
            }

            var result = AESEncryption.DecryptCBC256(Convert.FromBase64String(ciphertext), encryption_key, EncodingConverter.StringToByteArrayCaseInsensitive(IV));

            return(Encoding.UTF8.GetString(result));
        }