Based on what I have searched, AES256 CBC seems to be slower than AES256 GCM.
However today I test both modes on iPhone 13 Pro Max simulator and they makes me confused.
With AES256 CBC, I use an obj-c library called CommonCrypto, with AES256 GCM I use the CryptoKit https://developer.apple.com/documentation/cryptokit/aes/gcm
The result was with a string of 3MB, AES256 CBC 128-bit iv took 3s to encrypt or decrypt while AES256 GCM 96-bit iv took 10s!
What could be wrong here?
First of all, AES CBC should never be slower than GCM if each AES block cipher operation takes the same time. AES-CBC only performs a XOR between the block encrypts, and XOR's are so fast that the overhead should be negligible. AES-GCM however consists of counter (CTR) mode & GMAC calculations. CTR uses a 128-bit counter (negligible) and a XOR. However, the GMAC will have to be performed on top of that. It depends on the hardware how fast a Galois multiplication is, but it can be made relatively fast on ARM.
However, a lot depends on the implementation specifics. Objective-C is very fast and using managed code / swift may introduce an overhead, even if the actual implementation is again in C. This can especially hurt you if you don't allow for a warm up time in case an interpreter is used, as some operations will only be accelerated once they have been executed a few times.
CBC is quite often supplied as a streaming implementation, which means that the memory consumption can be relatively limited. If GCM only allows for everything in memory (as you want to verify the tag anyway before using the decrypted plaintext) then this may introduce overhead as well.
Note that if the key is stored in a key store vs memory then this may also make a lot of difference. Quite often the key will use a specific trusted environment if it is present in a key store, otherwise it would need to be copied out of the trusted environment to be used, which largely negates any benefit of having the trusted environment in the first place.
Finally, simulators are not emulators; they may not perform the operations in the same (relative) time. So relying on simulators for speed tests in itself is a flawed premise.
Speed tests are notoriously tricky to get right, and if you mix in cryptography then it just got a whole lot trickier.
Related
I am planning to create an application that has to be able to securely (that is, encrypted) send messages between clients. These messages may include images and videos (up to 50MB in size). Due to how public-key cryptography works, the encryption process has to be run once for each public key.
For these reasons, I am looking for an algorithm that can encrypt the media fairly quickly on modern devices (eg. mid-level smartphones).
I am asking the question because all algorithms I came across (Blowfish and RSA for example) have a relatively small payload limit, which means that even an image will not fit into it.
Don't roll your own protocol. You're thinking about this at a far too low level. People who know exactly what they're doing have a hard time writing secure code. You don't even know where to start, so you don't stand a chance of getting it right.
If you can establish a direct connection between the two endpoints, use TLS. If you can't establish a direct connection, consider using TLS and relaying the encrypted packets; if that's impractical, use Signal. TLS is ubiquitous; your operating system(s) probably come with an implementation in their default installation. Signal is less ubiquitous, so you'll probably have to embed a library. Make sure to keep up with updates to this library. And once again, don't implement your own library.
Under the hood, all systems that use public-key cryptography to store or transmit more than a few bytes of data use hybrid cryptography. Public-key cryptography is used to establish a symmetric key and authenticate the data, and symmetric cryptography does the heavy lifting.
For example, RSA can be used to encrypt a symmetric key. It's pretty difficult to get it right in practice, however. It's also slower than more modern methods that use elliptic-curve cryptography. TLS can use RSA encryption, but this is deprecated. TLS preferably uses an (elliptic curve) Diffie-Hellman key exchange and an RSA or (EC)DSA signature to set up the secure connection. If you'd like more explanations about how TLS works, read an overview of the protocol, a history of problems and how they were resolved, and an explanation of why RSA encryption is problematic.
Note that Blowfish has been obsolete for a while. If you ever need to choose a specific symmetric cryptosystem — which usually means you're doing it wrong — pick AES-GCM, AES-CCM or ChaCha20-Poly1305.
You are correct about the input size for RSA. In general, for any public key cryptography, the input size of limited and as opposed to your needs, it's quite a bit slower than what you need. Public key cryptography is usually used to share small pieces of data.
For example, in the TLS implementation using RSA (TLS_RSA_WITH_AES_128_GCM_SHA256), the RSA step is used to share a symmetric key, generally, AES, between 2 parties and then all the heavy lifting is done by AES.
What you need is a symmetric encryption algorithm. You can use AES (key sizes of 128, 192 or even 256) to encrypt your images which can be of any size. AES is a block cipher and, using a suitable block cipher mode, theoretically does not have an input limit to it. AES-128 is a fairly standard NIST approved (FIPS 197) symmetric encryption scheme, so it should be safe, but you can always go for a higher key size, say 256.
Since, you have the security of the algorithm defined, we can now talk about the speed.
RSA:
$ openssl speed rsa2048
Doing 2048 bit private rsa's for 10s: 296 2048 bit private RSA's in 10.00s
Doing 2048 bit public rsa's for 10s: 6171 2048 bit public RSA's in 9.99s
LibreSSL 2.6.5
built on: date not available
options:bn(64,64) rc4(ptr,int) des(idx,cisc,16,int) aes(partial) blowfish(idx)
compiler: information not available
sign verify sign/s verify/s
rsa 2048 bits 0.033784s 0.001619s 29.6 617.7
AES-128 in GCM mode
$ openssl speed aes-128-gcm
Doing aes-128 gcm for 3s on 16 size blocks: 3778792 aes-128 gcm's in 2.99s
Doing aes-128 gcm for 3s on 64 size blocks: 1611239 aes-128 gcm's in 3.00s
Doing aes-128 gcm for 3s on 256 size blocks: 485243 aes-128 gcm's in 2.99s
Doing aes-128 gcm for 3s on 1024 size blocks: 125054 aes-128 gcm's in 2.99s
Doing aes-128 gcm for 3s on 8192 size blocks: 15366 aes-128 gcm's in 2.96s
LibreSSL 2.6.5
built on: date not available
options:bn(64,64) rc4(ptr,int) des(idx,cisc,16,int) aes(partial) blowfish(idx)
compiler: information not available
The 'numbers' are in 1000s of bytes per second processed.
type 16 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes
aes-128 gcm 20220.96k 34373.10k 41545.89k 42827.86k 42526.44k
You can see the difference, how AES can blow away RSA in the dust with respect to speed. Symmetric Encryption algorithms are inherently faster due to its design. Asymmetric algorithms use math operations on huge numbers and primes which are slower.
Since AES is so popular, CPU manufacturers started implementing special instructions to make AES computations more and more native (AES-NI). So AES will be faster on almost all popular CPUs.
A small note on security between RSA and AES, although it's like comparing apples to oranges.
RSA2048 offers only 112 bits of security whereas AES128 offers 128 bits of security (ref: aes-vs-rsa)
Another challenge in the above problem would be key management. How would you safely manage the keys? If the keys are to be ephemeral, i.e. session based or one key per use, then you can use RSA to exchange symmetric keys and then perform the encryption. This would guarantee perfect forward secrecy. If you want persistent keys, then obviously there are much more elaborate methods to do that which is out of scope of this question.
RSA , no doubt, has several applications and is very famous. And today we use 2048-bit RSA key for security purposes. Yet, I see several research papers implementing RSA algorithm with 32-bit key (or more) on FPGAs.
http://ac.els-cdn.com/S1877050914009478/1-s2.0-S1877050914009478-main.pdf?_tid=a6e0e2de-edcd-11e5-9656-00000aab0f26&acdnat=1458390502_b193a360ee3dad04b27a38b33d3e113a
http://research.ijcaonline.org/volume92/number8/pxc3894226.pdf
What is the purpose of it? 32-bit algorithm is easily crackable.
Only Montgomery method is effective approach to RSA implementation in FPGA.
The advantage is ratio of the: technology cost, obtained bandwidth and power consumption.
This ratio for PC computer with OS is relatively weak.
Sorry for My English.
Why on FPGA?
Because a hardware implementation is more efficient and offloads the CPU. That is more relevant for small devices, think IoT.
Even if we do, then we end up with 32 or 64 bit key
That seems to be an artifact of the fact that this is research. One of those papers mentions "It is verified that this architecture support multiple key of 128bits, 256bits, and 512 bits"
Still not something I would like to use for my bank transactions but for data packets of low value, or only valuable or a short time period, even 128 bits might be acceptable.
I am trying to use asymmetric encryption to encrypt firmware. The bootloader will decrypt and update the flash. This is on a embedded device with 32 bit CPU executing at 60MHz.
I want to use ECC due to its varies advantages. I am new to encryption and my understanding os ECC as implemented in ECIES is to use ECC for the key generation and use AES for actual data encryption. Due to code and ram size, I cannot support multiple encryption algorithms.
Is there a implementation of ECC that can be used just like AES. All I am looking for is to use a "Private key" to encrypt firmware and the bootloader uses "Public Key" to decrypt it.
Thanks.
I'm not sure that you completely understand what ECIES consists of:
http://en.wikipedia.org/wiki/Integrated_Encryption_Scheme
That's quite a bit of work, and it requires a whole lot of primitives, including at least one symmetric primitive, it seems to me. That might as well be AES.
Let's start from the last sentence of the question:
All I am looking for is to use a "Private key" to encrypt firmware and the bootloader uses "Public Key" to decrypt it.
There's some confusion in terminology here. Private keys are used to decrypt (or sign) and public keys are used to encrypt (or verify). If I understand correctly, what you want is for the bootloader to verify a signature on the firmware so that only a firmware that was properly signed by yourself will be accepted by the bootloader.
There are various asymmetric signature schemes which can be used for this purpose, including some which are based on eliptic curve cryptography. For example you could use the OpenSSL implementation of ECDSA (see http://www.openssl.org/docs/crypto/ecdsa.html).
I'm afraid there's not enough information in the question to properly choose the best signature scheme (and possibly an encryption scheme as well if there is a need to keep the firmware secret). In any case, good cryptography is not enough to make a system secure and other considerations such as secure implementation are no less important.
If this is is something that is important for you to protect and that you are worried that hackers may try to break, I would strongly advise procuring the services of a security professional. Using cryptography correctly is a very tricky business that requires a full understanding of the system - otherwise you may find yourself in a situation like this
If you look for "authentication" you have to use asymmetric algorithm like EC, this usually done because if the user or process want to update the "firmware" he should identify him self to the bootloader by his "signature" to check who request this update.
After that is done, the bootloader will load the symmetric key from a secure memory to decrypt what you want to do.
So, you have a symmetric key for encryption (AES), and asymmetric two keys for authentication (=Who are you?).
Note: there is no advantages of EC on 32 bit CPU executing at 60MHz for Encryption, unless your application need asymmetric for Encryption NOT authentication, this happen due to line between the user and bootloader is not secure.
Therefore, you could use bootloader's "public key" to encrypt firmware and the bootloader uses its "private Key" to decrypt it, however, the implementation cost a lot due to the high computing for asymmetric algorithm.
Look for "lightweight cryptography", it is typical for your application.
Introduction:
For my personal webserver I have setup apache with a self signed certificate to enable TLS security to learn and test.
I have this line in virtualhost:
SSLProtocol -all -SSLv3 +TLSv1
SSLCipherSuite TLSv1:+HIGH:!MEDIUM
With firefox, I get Camellia-256 encrypted connection, and with opera I get TLS v1.0 256 bit AES (1024 bit DHE_RSA/SHA) with the same config in same server.
That leads me to question, which is stronger, AES, or Camellia?
I noticed that if I disable camellia with SSLCipherSuite TLSv1:+HIGH:!MEDIUM:!CAMELLIA then, firefox takes the same suite than opera.
In my config, I also try to disable all SSL versions to enable only TLS (advise needed if I didn't do so correctly), but the original question still stands: Which one should be stronger?
I would be more worried about the fact that your SSL encryption is not secure because you are only using 1024 bit asymmetric encryption to protect your keys.
Adi Shamir (the 'S' in RSA) recommended moving to 2048 bit keys back in 2006, even the american standards institute (NIST) have made 2048 bit a required minimum strength since January 2011 (see NIST SP800-57 for recommended minumum key strengths -- this states 2048 bit for both RSA and DH/el-gamal).
In short, make sure your RSA encryption is strong enough first, as it is used to protect the symmetric keys (AES/Camellia). Never rely on a key which is protected by a weaker key (this is like using a secure 256 bit random WPA 2 key on a wireless access point and then trusting it to WPS which will reveal in in a few hours!)
Even if this is a test system, learn to use crypto the way you intend to go forward; do not compromise on certificate key strength (all CAs these days should reject 1024 bit requests or CSRs using MD5 on sight, if not don't use them; create your own test certs as you would a real request, and don't use default key sizes).
Difficult to compare strengths, both have received cryptographic analysis (AES more publicly) and are adequate for securing data.
At the risk of repeating myself, I’d be more worried about the 1024 bits used to secure the key negotiation.
It's hard to judge the strength of these algorithms. Camellia is considered roughly equivalent to AES in security (source). In any case, the difference probably won't matter. Either algorithm is secure enough to make your data channel no longer be the weakest link in your system, so you don't need to bother modifying any configuration.
The OpenSSL cipherlist TLSv1:+HIGH is a really bad choice. The "+something" notation means move all the ciphers that match "something" to the end of the list.
Therefore, you're using HIGH only as a last resort, with anything that's not HIGH preferred.
A much better choice is "DEFAULT:!MEDIUM:!LOW:!EXPORT:+3DES", which starts with sensible defaults, removes MEDIUM, LOW and EXPORT, and uses 3DES last (which it probably is anyway, but on some systems it comes before AES128 because it may be considered to be 168-bit strong).
I have a pair of transceivers connected to the micro-controller from Port A, and a MM232R connected to Port B on a separate PCB. Each transceiver will send encrypted data, while MM232R will receive a decrypted data. I need write encryption algorithm and decryption code. Can anyone give me idea on how to go about it? I am new to programming and encryption algorithm.
I'm not sure about the ROM/RAM limits of the PIC18F1320, that is the main constraint.
This page contains an implementation of AES on a PIC18F4620. It uses 2K words of ROM and 240 bytes of RAM.
This other page seems to have an implementation of RSA on a PIC18F4550, but it warns that it is very slow (which does't surprise me, since RSA encryption requires modular arithmetic on large integers).