When creating the instance, the KEY and IV are generated for me.
RijndaelManaged myRijndael = new RijndaelManaged();
How can I store the Key in my database or web.config file?
And in what format?
Because I will have to load the key when trying to decrypt the encrypted string obviously.
thanks for your help, a little lost on this topic.
When storing binary as text (regardless if to a text file or a database field), the Base64 encoding is the way to go.
RijndaelManaged myRijndael = new RijndaelManaged();
// to Base64
string keyb64 = Convert.ToBase64String(myRijndael.Key);
// reverse
myRijndael.Key = Convert.FromBase64String(keyb64);
The Base64 string is safe to store anywhere you like.
Related
I tried encrypting a string in dart using encrypt library and It works pretty well other than the fact that when I try the generated encrypted string and the key and iv in an online AES decryptor, It never decrypts successfully.
I want to send encrypted data to a server and then that data needs to be decrypted on the server as well as the mobile device and I couldn't find any solution for this
My server is using PHP with OpenSSL, and I couldn't find any library for openSSl in flutter except this one but it has 0 documentation.
This is the sample code I used
Attempt 1:
final plainText = 'My Phone number is: 1234567890';
final key = encrypt.Key.fromLength(32);
final iv = encrypt.IV.fromLength(16);
final encrypter = encrypt.Encrypter(encrypt.AES(key));
final encrypted = encrypter.encrypt(plainText, iv: iv);
final decrypted = encrypter.decrypt(encrypted, iv: iv);
print(key.base64); // prints AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
print(iv.base64); // prints AAAAAAAAAAAAAAAAAAAAAA==
print(encrypted.base64); // prints kezgKMov5+yNJtd58OFSpzp8sNv2dwWNnFWDyf37cYk=
Attempt 2:
This time I used this gist that works using pointy castle to create the same data, but this time the IV was generated in an Array, and my server is expecting it as an int or a string.
Attempt 3:
this time I tried again using encrypt and found a medium link that encrypts data for decryption in the web using cryptoJS. this made me think, are all AES encryption libraries not compatible with each other?
final plainText = 'My Phone number is: 1234567890';
final newKey = Utils.CreateCryptoRandomString(32); // value is lh1uCZN4c8AFL2P4HudHV8B7dEBLzjxarZ09IrCf9cQ=
final encryptedAES = encryptAESCryptoJS(plainText, newKey);
Inside the encryptAESCryptoJS function, I added print statements to print the generated Salt, IV and key, Here are those:
SALT = [112, 161, 85, 133, 146, 178, 232, 83]
KEY = 0IfSLn8F33SIiWlYTyT4j7n6jnNP74xNaKTivqNeksE=
IV = QCl8fNQtg+QQYTQCINV6IA==
I can encrypt and decrypt locally easily using all the methods, but how can I add support so that the encrypted data can be decrypted on the server as well.
some of the websites I tried using to decrypt the data were
https://string-o-matic.com/aes-decrypt
and
https://www.devglan.com/online-tools/aes-encryption-decryption
both threw errors on adding the key, and iv on the specified fields
Any help would be much appreciated.
couldn't find any library for openSSl in flutter except this one but it has 0 documentation.
Yes, seems this is a problem. As well I consider important that someone understands basics regardless of the language implementation
I want to send encrypted data to a server and then that data needs to be decrypted on the server as well as the mobile device and I couldn't find any solution for this
That is a task of the TLS
The data needs to be stored encrypted as well so that no one working in the backend can look at the data
Just use the same encryption and decryption parameters. The problem with your code I see is it's missing some of the parameters and using defaults (defaults can differ in different libraries) or assuming you are using different parameters.
Symmetric encryption (AES specifically) needs to define:
key - for AES it's always 128, 192 or 256 bit (depending on the strength). Some libraries zero-pad or trim the input to match the required key length what I consider a terrible practice. Simply - a key needs to be a byte array of the specific length.
When encrypting multiple blocks of data:
padding - how input is padded to match the encryption block size (usually pkcs#7 padding)
mode of operation
IV - see the documentation about the mode of operation, IV must be unique and for some modes IV needs to be unpredictable (random).
SALT is used to create an encryption key from a password. So where you see any salt in use, check if you are providing a key or a password. Password can have any length and is usually user-handled (having lower entropy) and there are multiple ways how to derive a key from the password and salt.
var encrypted = encryptAESCryptoJS(plainText, "password");
See the source code, the encryptAESCryptoJS expects a password as input and then generates a salt and derives a key and IV (this is a practice from OpenSSL, but may not be compatible with other libraries).
This is a problem with some libraries, mainly when missing documentation.
Are all AES encryption libraries not compatible with each other?
AS cipher is AES cipher. You need to get the Cipher, Key, Padding, IV and the mode of operation the same for encryption and decryption regardless the programming language or platform. There are some most common defaults (AES-128, CBC mode, PKCS#7 padding, ..) but it's better to properly specify the parameters to be sure.
but this time the IV was generated in an Array, and my server is expecting it as an int or a string.
Encryption always works on top of byte arrays. You may encode a byte array as base64 or hex encoded string.
Edit: extra security measure
What I miss in this solution (in many other solutions in fact) is an authentication tag. Most of the encryption modes are malleable, the ciphertext can be changed and then the decryption would successfully decrypt to a different plaintext without detecting any problem with integrity. I consider using any HMAC necessary, but missing in many implementations.
I had the same problem, since in php the openssl_decrypt with aes-256-cbc is used to decrypt but in dart it didn't work for me, until I found a code snippet on github solutions, which served as the basis for proposing a solution to make it decode a text encrypted with php Lumen and AES openssl, I hope it will help you.
// code decrypt in PHP
$key = '**********key secred';
$encrypted = $request->get('encrypted');
$payload = json_decode(base64_decode($encrypted), true);
$iv = base64_decode($payload['iv']);
$decrypted = openssl_decrypt($payload['value'], 'aes-256-cbc',
base64_decode($key), 0, $iv, '');
$response['decrypted'] = unserialize($decrypted);
return $this->successResponse($response);
/// code decrypt in dart
import 'dart:convert';
import 'package:encrypt/encrypt.dart' as enc;
import 'dart:async';
import 'package:php_serializer/php_serializer.dart';
Future<String> decryptInfo(String data) async {
var encodedKey = 'FCAcEA0HBAoRGyALBQIeCAcaDxYWEQQPBxcXH****** example';
var decoded = base64.decode(data);
var payload = json.decode(String.fromCharCodes(decoded));
String encodedIv = payload["iv"]?? "";
String value = payload["value"] ?? "";
print(decoded);
print(payload);
print (encodedIv);
final key1 = enc.Key.fromBase64(encodedKey);
final iv = enc.IV.fromBase64(encodedIv);
final encrypter = enc.Encrypter(enc.AES(key1, mode: enc.AESMode.cbc));
final decrypted = encrypter.decrypt(enc.Encrypted.fromBase64(value), iv: iv);
print(phpDeserialize(decrypted));
return decrypted;
}
I have an app that writes data to a file line by line. Once finished, the data needs to be zipped and transmitted to a server. I want to make sure that after zipping but before transmitting the data to the server, the data is secure. Thus, I want to encrypt the zip (or the contents). Moreover, I want to use asymmetric encryption because the source code will be viewed by others.
Is there any way to do this in flutter/dart?
My alternative solution would be to read the data back into the app, encrypt it, write it again, and then zip it. What are your thoughts?
As #Topaco accurately stated, asymmetric encryption of a large file comes with important performance drawbacks.
It can be achieved by splitting the file into smaller chunks of data and encrypting each part. But again, this is not recommended.
That said, you encrypt/decrypt a String with RSA using the rsa_encrypt package for Flutter:
import 'package:rsa_encrypt/rsa_encrypt.dart';
import 'package:pointycastle/api.dart' as crypto;
//Future to hold our KeyPair
Future<crypto.AsymmetricKeyPair> futureKeyPair;
//to store the KeyPair once we get data from our future
crypto.AsymmetricKeyPair keyPair;
Future<crypto.AsymmetricKeyPair<crypto.PublicKey, crypto.PrivateKey>> getKeyPair()
{
var helper = RsaKeyHelper();
return helper.computeRSAKeyPair(helper.getSecureRandom());
}
/*
- Generate KeyPair with the function getKeyPair() store the returned value in futureKeyPair.
- Once we get data from the future we can store that data in keyPair (Now we have acces to our private and public key).
- In order to view our keys as "a string" we need to use two functions encodePrivateKeyToPemPKCS1(keyPair.privateKey) & encodePublicKeyToPemPKCS1(keyPair.publicKey).
- In order to encrypt and decrypt strings you can use two functions
- encrypt() : use this function to encrypt a string, pass your string as first argument and a public key as the second one. [IMPORTANT]: this will return a string so you should store the returned value in a variable.
- decrypt() : use this function to decrypt an encrypted String, pass your encrypted String as first argument and a private key as the second. this will also return a string dont forget to store it :)
*/
A solution to encrypt a file would be to use a safe symmetric encryption algorithm with a random secret key, which is then encrypted with an asymmetric algorithm. This approach is commonly referred to as hybrid cryptosystem.
I have a string:
RP581147238IN which gets encoded as A3294Fc0Mb0V1Tb4aBK8rw==
and another string:
RP581147239IN which gets encoded as A3294Fc0Mb1BPqxRDrRXjQ==
But after spending a day, I still cannot figure out what is the encoding process.
The encoded string looks like its base64 encoded.
But when I decode it, it looks like:
base64.decodestring("A3294Fc0Mb0V1Tb4aBK8rw==")
\x03}\xbd\xe0W41\xbdA>\xacQ\x0e\xb4W\x8d
The base 64 decoded string now is looking like a zlib compressed string
I've tried to further use zlib decompression methods but none of them worked.
import zlib, base64
rt = 'A3294Fc0Mb1BPqxRDrRXjQ=='
for i in range(-50, 50):
try:
print(zlib.decompress(base64.decodestring(rt), i));
print("{} worked".format(i))
break
except:
pass
But that did not produce any results either.
Can anybody figure out what is the encoding process used here. #Nirlzr, I am looking at you for the heroic answer you provided in Reverse Engineer HTTP request.
The strings seem to be Base64 encoded and the underlying decoded data seems to be encrypted. Encrypted data can not be directly represented as a string and it is common the Base64 encode encrypted data when a string is required.
If this is the case you need to decrypt the decoded data and ignorer to accomplish that you would need the encryption key.
Note: In general it is not productive to compress such short items.
If you put your data strings side by side:
RP581147238IN A3294Fc0Mb0V1Tb4aBK8rw==
RP581147239IN A3294Fc0Mb1BPqxRDrRXjQ==
You can see that source strings have only character difference, but encoded version contains 12 different characters:
----------8-- ----------0V1Tb4aBK8rw--
----------9-- ----------1BPqxRDrRXjQ--
Encoded data has similar paddings at the end as base64, but definitely it is not base64. Probably crypted with some SHA-like algorithm. With the data you provided, I would say that it is not possible to reverse-engineer the encoding process. Probably more data would not help much either.
while trying to login into a site I've stumbled upon having to send a piece of text encrypted with RSA being given two parameters - a 1024 byte long pub key modulus (512characlers) and a pub key exp:
publickey_mod = C0B25EA7A3E1563B7613D6529F474D1609AD885BAD810F1708A9622029517FD6B38270ED776D4F1ACDEB738CC2ABDED7F5A8119A1E8CB565CA2A4FCDC119A7FCE73767A758DEABB332D1D04E4673E3E1A09BE5AE91F1129A1B993604FB529F8D5F45F1E153D9D0DEB74ECFEA1FC09D819FE719FC3D5A19637D19E84EFECCCA8B25C094973EAFAB78EF0BFE69CA18627477BE9E7B694CC87E57AC3E0BAB40EA33F189D139A75A5CC1D59505F9FD7AC657D993DE70196DA2552C91002CD581A11BCF26BF8FB2C683799C2585C99521295A1E23B7588DD3429E6C8907F4E4502D9C9B3D5B8DEBA2B1EA0F339995082D5658A0D8FCE56177E132A83A5EBABEA14413
publickey_exp = 010001
After encoding, we should be left with something like:
DtvB78BFPVRquP5fQ7CTrdlFboOG3AM5MA3yDKfdZyZbQuCQJL5vaht7XM721D%2BB8kUvG8ZVP%2Bif15ZeusZjikjAvjK%2BrlhoNJmYMnDIZ7avebvYi9PwiegjiEukfgm5dDKJ7Zn%2BRXXog543qPSSGjAj0hhHJFiRP1z33NwBqQbSQFcCxi%2FG4GWFKBomB%2FHqV3wnBDaW8N%2Brx%2FZxUIF1Q2k7SrtGgYr%2FT29ZuEqlEFyM%2FgiAgdk8jO%2F4h0rs%2FuB0lvG4NGhfp4%2BvGDAQ9iCvhwIsGFmwmqB%2Ff1oxhAcSpr8npWRePw3SZLlpoNT31pU9lSPUbvhAg8Hh2S83L9kotw%3D%3D
Any ideas?
The Base64 encoded string is further URL encoded. You can skip the steps of manually replacing the +, / and = by using java's URLEncoder:
encrypted = URLEncoder.encode(encrypted,
java.nio.charset.StandardCharsets.UTF_8.toString());
More details in : https://docs.oracle.com/javase/7/docs/api/java/net/URLEncoder.html
I have created code which takes a string from a text field and calls a encrypting method for doing encryption of that text using the base64 encoding scheme. But I don't have any idea how to create the decryption method for decrypting whatever value I am getting from the method.
Save yourself some trouble and download the NSData Base64 category.
Then you can encode or decode using a single line.