-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Password-based AES CBC encryption? #35
Comments
If you want to handle passwords, you'll need [PassCrypt]. You should use scrypt; that's the securest function we support. Password hashing should always be one-way, meaning that you can't retrieve the plaintext of the password. Use a key-value store (like https://pub.dev/packages/hive) and map a SHA-hashed username to the scrypt-hashed password + generated salt. Then, you can do password verification off this copy. I've written a small code sample below to see what this looks like. Keep in mind that this code sample will be outdated when steel_crypt 2.0 comes out! void map (String key, String value) {
// Store the key and map it to a value in your database.
}
String getFromMap (String key) {
// Get the value mapped to 'key' in your database.
}
String createAccount (String username, String password) {
var salt = CryptKey().genDart();
var userHash = HashCrypt('SHA-3/256').hash(username);
var passHash = PassCrypt('scrypt').hashPass(salt, password);
var passHash += salt;
map(userHash, passHash);
}
bool isCorrectPassword (String usernameInput, String passInput) {
var key = HashCrypt('SHA-3/256').hash(usernameInput);
var correctHash = getFromMap(key);
var salt = correctHash.sublist(correctHash.length-16, correctHash.length);
var correctHash = correctHash.sublist(0, correctHash.length-16);
var inputHash = PassCrypt('scrypt').hashPass(salt, passInput);
return inputHash == correctHash;
} |
Note that both [createAccount] and [isCorrectPassword] will take a while to run; this is necessary for security and impossible to solve.. You might want to make Future wrapper functions so that they can be asynchronous and not block the main thread. |
Sorry just realized I may have not quite answered your question. This is how you would handle just the username and password. To encrypt/decrypt additional data using AES and password as the key: String encryptAES (String plain, String username) {
var dbKey = HashCrypt('SHA-3/256').hash(username);
var iv = CryptKey().genDart();
var aesKey = getFromMap(dbKey);
aesKey = PassCrypt().hashPass(iv, aesKey.substring(0,32));
var aesEncrypter = AesCrypt(aesKey, 'gcm', 'pkcs7');
var output = aesEncrypter.encrypt(plain, iv);
output += iv;
return output;
}
String decryptAES (String encrypted, String username) {
var dbKey = HashCrypt('SHA-3/256').hash(username);
var aesKey = getFromMap(dbKey);
var iv = encrypted.substring(encrypted.length-16, encrypted.length);
aesKey = PassCrypt().hashPass(iv, aesKey.substring(0,32));
var aesEncrypter = AesCrypt(aesKey, 'gcm', 'pkcs7');
var original = aesEncrypter.decrypt(encrypted.substring(0, encrypted.length-16), iv);
return original;
} This integrates with the above example I created. You really should be using the above example (or something very similar) if you have a username/password system. Additionally, you really should have a username/password system if you have passwords involved. |
Thanks for the prompt replied and answer! |
what does getFromMap method should do? |
There are few encryption library available for Flutter but this look more reliable library because of documentation or simpleness.
The key and ivsalt are generate randomly each time, how can I achieve the password-based encryption?
I'm not familiar with crypto, maybe is AES/CBC/PKCS5PADDING?
The text was updated successfully, but these errors were encountered: