How to encrypt altbeacon to aes-ecb format.
I have been using flutter but on flutter side.
I guess it can't be encrypted as the data passed to altbeacon library is in beacon data format.
beaconTransmitter?.startAdvertising(beacon, object : AdvertiseCallback() {
override fun onStartSuccess(settingsInEffect: AdvertiseSettings?) {
super.onStartSuccess(settingsInEffect)
advertiseCallback(true)
}
Using encryption with bluetooth beacons is very complex for a number of reasons:
Bluetooth beacons have a small payload of about 22 usable bytes, which is way too small for a full encrypted message. As a result, beacons typically use a one-way hash that is stripped down to a smaller number of bytes after applying a specific encryption algorithm.
Standard beacon formats like iBeacon, AltBeacon and Eddystone-UID divide up this limited payload into fields that are meant to be clear-text (unencrypted) identifiers.
Formats like Eddystone-EID which do use encryption require complex systems to configure each beacon transmitter with a clock-specific hash, and then decode this using a matching algorithm on the receiving side. They then strip down the encrypted payload to just a few bytes.
If you want to crate a hash with an encryption algorithm and then pare the result down to an 8-byte payload, you can transmit it in an Eddystone-EID frame like below. Just replace the 8 bytes in "0x0001020304050607" with your hashed data.
Beacon beacon = new Beacon.Builder()
.setId1("0x0001020304050607") // Encrypted Identifier
company code
.setTxPower(-59)
.build();
BeaconParser beaconParser = new BeaconParser()
.setBeaconLayout(BeaconParser.EDDYSTONE_EID_LAYOUT);
BeaconTransmitter beaconTransmitter = new BeaconTransmitter(getApplicationContext(), beaconParser);
beaconTransmitter.startAdvertising(beacon, new AdvertiseCallback() {
#Override
public void onStartFailure(int errorCode) {
Log.e(TAG, "Advertisement start failed with code: "+errorCode);
}
#Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
Log.i(TAG, "Advertisement start succeeded.");
}
});
For this to be compliant with the Eddystone-EID spec, there are very specific requirements you need to take in producing your hashed bytes. If you don't care about meeting the spec, you are welcome to generate those bytes any way you wish so long as they meet your own use case.
Related
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.
We are developing and using the Ionic 3 Native AES 256 algorithm to encrypt the data, the out put of encrypted data is not valid format of ciphertext format(24 byte). so that we can't able to decrypt in java programme side. also our middleware team using AES/GCM/NoPadding but ionic native plugin using AES/CBC/PKCS5PADDING so that we could not able to decrypt the data in java based middleware side. please advise, how do we handle this.
ionic docs : https://ionicframework.com/docs/v3/native/aes256/
As commented in your first question regarding this topic
(ionic v3 AES 256 algorithm to using encrypted not able to decrypt in java AES/GCM/noPadding algorithm) I run the ionic encryption with these data:
password = "test#123"
plaintext = "Test1234"
and received a Base64-encoded ciphertext string like "izMYpAIMvsCKIVjiNztsrA=="
(as the encryptionKey & iv is generated with random elements your results will differ).
Decoding this ciphertext string back to a byte array I get a (byte array) length of 16 and NOT 24 (it has to be always a multiple of 16) so your encryption isn't running well when getting a length of 24!
Second: there is no way to work with different AES modes - ionic does only support CBC mode that has to be used on your middleware decryption as well. If you need to use an authenticated encryption like "GCM" mode you have to use an additional library.
I was looking for a good encryption scheme to encrypt my message and i founded that the Hybrid encryption is good for large and small messages. but i have a problem with the length of the output cipher message which is large.
if the input was "hello", then the length of the output message will be 586, and twice if if the message larger
here is the Encrypt function that i use:
def encrypt(username, msg):
#get the reciever's public key
f = open("{}.pem".format(username)) # a.salama.pem
recipient_key = RSA.import_key(f.read())
f.close()
# Encrypt the session key with the reciever's public RSA key
cipher_rsa = PKCS1_OAEP.new(recipient_key)
# Encrypt the data with the AES128 session key
session_key = get_random_bytes(16)
cipher_aes = AES.new(session_key, AES.MODE_EAX)
ciphertext, tag = cipher_aes.encrypt_and_digest(msg)
#finishing your processing
encrypted_data = cipher_rsa.encrypt(session_key) + cipher_aes.nonce + tag + ciphertext
encrypted_data = hexlify(encrypted_data).decode("utf-8")
return encrypted_data
There's a fixed number of extra bytes in the header regardless of the amount of plaintext being encrypted. That's evident from your line of code
encrypted_data = cipher_rsa.encrypt(session_key) + cipher_aes.nonce + tag + ciphertext
This extra data will be dominated by the RSA-encrypted session key. A more space-efficient choice would be ECIES using a well-known 256-bit elliptic curve.
However, you also have expansion of the data due to encoding. Your choice of encoding is hex encoding which doubles the amount of data. A more efficient and well-supported encoding is base64 encoding. Base64 encoding expands the data by a factor of 4/3. The most space-efficient is avoid encoding altogether and just store and transmit raw bytes. You only need to encode the data if it will transit over channel that cannot handle binary data.
OK, I'm probably just having a bad Monday, but I have the following need and I'm seeing lots of partial solutions but I'm sure I'm not the first person to need this, so I'm wondering if I'm missing the obvious.
$client has 50 to 500 bytes worth of binary data that must be inserted into the middle of a URL and roundtrip to their customer's browser. Since it's part of the URL, we're up against the 1K "theoretical" limit of a GET URL. Also, $client doesn't want their customer decoding the data, or tampering with it without detection. $client would also prefer not to store anything server-side, so this must be completely standalone. Must be Perl code, and fast, in both encoding and decoding.
I think the last step can be base64. But what are the steps for encryption and hashing that make the most sense?
I have some code in a Cat App that uses Crypt::Util to encode/decode a user's email address for an email verification link.
I set up a Crypt::Util model using Catalyst::Model::Adaptor with a secret key. Then in my Controller I have the following logic on the sending side:
my $cu = $c->model('CryptUtil');
my $token = $cu->encode_string_uri_base64( $cu->encode_string( $user->email ) );
my $url = $c->uri_for( $self->action_for('verify'), $token );
I send this link to the $user->email and when it is clicked on I use the following.
my $cu = $c->model('CryptUtil');
if ( my $id = $cu->decode_string( $cu->decode_string_uri_base64($token) ) ) {
# handle valid link
} else {
# invalid link
}
This is basically what edanite just suggested in another answer. You'll just need to make sure whatever data you use to form the token with that the final $url doesn't exceed your arbitrary limit.
Create a secret key and store it on the server. If there are multiple servers and requests aren't guaranteed to come back to the same server; you'll need to use the same key on every server. This key should be rotated periodically.
If you encrypt the data in CBC (Cipher Block Chaining) mode (See the Crypt::CBC module), the overhead of encryption is at most two blocks (one for the IV and one for padding). 128 bit (i.e. 16 byte) blocks are common, but not universal. I recommend using AES (aka Rijndael) as the block cipher.
You need to authenticate the data to ensure it hasn't been modified. Depending on the security of the application, just hashing the message and including the hash in the plaintext that you encrypt may be good enough. This depends on attackers being unable to change the hash to match the message without knowing the symmetric encryption key. If you're using 128-bit keys for the cipher, use a 256-bit hash like SHA-256 (you can use the Digest module for this). You may also want to include some other things like a timestamp in the data to prevent the request from being repeated multiple times.
I see three steps here. First, try compressing the data. With so little data bzip2 might save you maybe 5-20%. I'd throw in a guard to make sure it doesn't make the data larger. This step may not be worth while.
use Compress::Bzip2 qw(:utilities);
$data = memBzip $data;
You could also try reducing the length of any keys and values in the data manually. For example, first_name could be reduced to fname.
Second, encrypt it. Pick your favorite cipher and use Crypt::CBC. Here I use Rijndael because its good enough for the NSA. You'll want to do benchmarking to find the best balance between performance and security.
use Crypt::CBC;
my $key = "SUPER SEKRET";
my $cipher = Crypt::CBC->new($key, 'Rijndael');
my $encrypted_data = $cipher->encrypt($data);
You'll have to store the key on the server. Putting it in a protected file should be sufficient, securing that file is left as an exercise. When you say you can't store anything on the server I presume this doesn't include the key.
Finally, Base 64 encode it. I would use the modified URL-safe base 64 which uses - and _ instead of + and / saving you from having to spend space URL encoding these characters in the base 64 string. MIME::Base64::URLSafe covers that.
use MIME::Base64::URLSafe;
my $safe_data = urlsafe_b64encode($encrypted_data);
Then stick it onto the URL however you want. Reverse the process for reading it in.
You should be safe on size. Encrypting will increase the size of the data, but probably by less than 25%. Base 64 will increase the size of the data by a third (encoding as 2^6 instead of 2^8). This should leave encoding 500 bytes comfortably inside 1K.
How secure does it need to be? Could you just xor the data with a long random string then add an MD5 hash of the whole lot with another secret salt to detect tampering?
I wouldn't use that for banking data, but it'd probably be fine for most web things...
big
We're developing a service that will accept a POST request. Some of the POST data will need to be encrypted before the POST as it will be stored in hidden fields on a form.
The application is written in C#, but we want third party clients to be able to easily integrate with it. We find that most clients use PHP, Classic ASP or VB.Net.
The third parties should only be doing the encryption. We'd do the decryption. There is no two-way communication.
What are the most compatible combinations of encryption algorithm, padding mode and other options?
Assuming that you have a safe way of sharing a key (whether RSA encryption of it, retrieval over an SSH or HTTPS link, or callling the other developer on a secured phone line), any of the major modern encryptions (like AES, as mentioned by #Ed Haber) would be suitable. I would second his suggestion of AES. There should be libraries for PHP, VB, Ruby, etc.
However, remember that with "no two-way communication" you will have to find an out-of-channel method for securely getting the symmetric key to the encrypting party.
If you mean that it should be impossible for third-parties to decrypt data, then you will want to use an asymmetric encryption algorithm such as RSA. This will the third-party to encrypt data with your public key, and then only you can decrypt the data with your private key, which you do not disclose. There should be implementations of RSA available for all the languages you mentioned.
If you don't care if the third-party can decrypt the data, then AES is the way to go. You will have one key which you share with the third-parties. This key is used both for encryption and decryption.
I would use AES for the bulk data encryption and RSA for encrypting the AES Key.
If the data is small enough then just encrypt the whole thing with RSA.
Ed Haber said
I would use AES for the bulk data
encryption and RSA for encrypting the
AES Key. If the data is small enough
then just encrypt the whole thing with
RSA.
I think this is a good solution. What I would do is have your application publish an API for getting a public RSA key. When I third party wants to send you something it gets the public key. It then generates a session key to do the actual encryption using a block cipher, (ie AES), and sends the key to you by encrypting with your public key. You decrypt the session key with your private key. The third party then encrypts the data it wants to send you with AES (using a padding scheme that you also publish) and sends it to you. You decrypt it using the session key.
There are some problems with the method above. Since you are not sending any information (other than publishing your public key, you cannot control how the session key is generated. This means that third parties can use very insecure ways to of generating the session key and you will never know. A second problem is everyone who wants to send you data has to pad data for AES in the same way you do. So you will have to make sure every one co-ordinates. The second issue isn't to big, but the first could be a problem especially if you don't trust the third parties all that much to generate really good session keys from a good cryptographically secure random number generator
You could very easily implement your own XOR key-based bit encryption. With a little thought and ingenuity, you can come up with something that's more than suitable for you application.
Here's a PHP example:
function XOREncryption($InputString, $KeyPhrase){
$KeyPhraseLength = strlen($KeyPhrase);
for ($i = 0; $i < strlen($InputString); $i++){
$rPos = $i % $KeyPhraseLength;
$r = ord($InputString[$i]) ^ ord($KeyPhrase[$rPos]);
$InputString[$i] = chr($r);
}
return $InputString;
}
ColdFusion has the encrypt and decrypt functions capable of handling a range of algorithms and encodings, including the AES recommended above.
Information at: http://www.cfquickdocs.com/cf8/?getDoc=encrypt#Encrypt
Quick example code:
Key = generateSecretKey( 'AES' , 128 )
EncryptedText = encrypt( Text , Key , 'AES' , 'Hex' )
Text = decrypt( EncryptedText , Key, 'AES' , 'Hex' )
Similar functionality is available with this library for PHP:
http://www.chilkatsoft.com/p/php_aes.asp
...and Java, Python, Ruby, and others...
http://www.example-code.com/java/crypt2_aes_matchPhp.asp
http://www.example-code.com/python/aes_stringEncryption.asp
Sounds like RSA is the algorithm for you.
Why not have your server exposed over HTTPS? That way, any client which can handle HTTPS can consume the service securely.