We are putting an HTTP RESTful interface into an embedded platform of ours. The hardware is too limited to support SSL, but we do use AES encryption for other things.
I'm thinking of using AES with a shared key to encrypt the data. Is there anything else that is at least a somewhat standard way of encrypting via HTTP?
The standard way of encrypting HTTP is SSL (or its successor TLS, nowadays) (this is then known as HTTPS).
As GregS asked in a comment, in what way is your platform too limited for SSL, but still allows AES? Does it have not enough computing power/memory to do modular exponentiation (which is used in RSA, DSA, Diffie-Hellman)?
Then you might be able to use a pre-shared key version of TLS. RFC 4279 defines cipher suites with pre-shared key authentication, where the TLS_PSK_WITH_AES_128_CBC_SHA looks like if needs only AES and SHA-1, no modular exponentiation.
Of course, you shouldn't use this if there is the danger that an attacker can get the secret (e.g. by cracking your device), since this allows also to read all previously registered connections (in contrast to Diffie-Hellman, which provides a new session key for each session).
Found this gem: Diffie-Hellman Key Exchange in 10 lines of C
http://www.cypherspace.org/rsa/dh-in-C.html
Related
I'm working on a project that take the GPS location every 5 seconds and send it to the server, but i need to make a little of security, so i need to encrypt the location in android device and decrypt it in server side, so i'm searching for a simple algorithm to do this
Thanks in advance
The ideas for you to try:
Send your data over HTTPS. It will add the layer of security you need and it's one of the simplest methods available.
Use Java Encryption API with asymmetric cryptographic algorithm like RSA. You should probably avoid using AES or similar symmetric algorithm because you should not store passphrase in your Android app - it could be quite easily compromised.
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).
Instead of spending a bunch of $$ on ssl, can I implement RSA on my own? (I don't care about proving the site's identity; I just want to encrypt a password between clients and the server to protect from man-in-the-middle attacks). I've read that any custom solutions are likely to be very insecure, but could someone read my plan and give a thoughtful response?
First I would create public and private keys. I would encrypt the client password with javascript by translating the letters of the password to ascii-values, and then multiply or add (any suggestions?) these ascii-values to get the "unencrypted message". I would then encrypt this message using javascript and the public key.
On the server, I would decrypt the secure message using the private key and end up with the sum/product of the password's ascii-values. Any tips on how to get the individual letters from that?
Edit: I've reached the conclusion that SSL is the best way to go. I was only looking at the client to server side of the deal (where all the client sends is a password). Of course, the information sent by the server to the client is valuable, and should not be vulnerable to MITM attacks. Thanks for the free SSL suggestions.
Thanks
There are a bunch of reasons not to roll your own encryption.
SSL gives the user confidence that the site is secure and that eavesdroppers cannot view the password on the wire. If you don't use SSL then the usual browser indications that the site is secure will not be present.
It's really hard to get RSA right (or any crypto algorithm for that matter). First off, using raw RSA is insecure and you need to have an appropriate padding mechanism and wotnot to make it actually secure. RSA can also only encrypt n-1 bytes of data, where n is the size of the key.
Leave crypto to the cryptographers. The first issue with your proposed system is that you're missing the point of using a secure transport: You don't need to do any special encoding of your data (the conversion to ascii and multiplying/summing or whatever part) because the secure transport means that eavesdroppers cannot see what's going past.
Your proposal does not protect against man-in-the-middle attacks. It (kinda) prevents eavesdropping, which is a different problem.
That said, you certainly can implement RSA in Javascript with a bit of effort, but just be aware that it is unlikely to be secure until you've had a bunch of cryptanalysts look at it and try to break it. You will make a mistake somewhere along the line, even if you are the best programmer in the world.
The user experience will also suffer because it will be very hard for the user to verify that they are, in fact, talking to your server.
SSL is a well known, well analysed, not-yet-broken protocol that can be free if you use a self-signed certificate (another poor user experience, but at least it's still fairly secure). Think very carefully before you decide to cheap out on the crypto, and make sure you weigh the cost of a certificate against your development time (it'll take you many hours to implement RSA) and the potential cost of leaking important customer information (their password). The cost of the certificate is likely to be insignificant compared to the rest of the project cost.
You can use a self-signed certificate on the server and trust it explicitly on the client (i.e. encode certificate parameters etc). So you don't need to reinvent the wheel. I would say more - depending on the library you can use PSK (pre-shared key) cipher suites and get rid of certificates completely.
I'm not sure you need SSL if you cannot afford a certificate. Obviously, your data you intend to protect does not have much value.
The public/private key system is best way to go. By the time you figure out how to roll your own and get your CA certificate included in all the major browsers and Operating Systems and become your own Certificate authority, I think you will find spending a few 100$ on cert is cheap.
If you are looking for SSL but not spending money use www.startssl.com as that will allow you to use SSL free. Creating your own solution will take time and if not done the correct way will be insecure.
Yes, it is possible to implement plain RSA "by hand" in this way. To create the unencrypted message, you can simply use the bits of the message. For example, if your password is cheese:
c h e e s e
0x63 0x68 0x65 0x65 0x73 0x65
The number to encrypt could then be simply 0x636865657365. You'll need to use math routines that can handle large integers (native Javascript numbers aren't big enough).
Standard warnings apply, your solution will have a fatal flaw in some way, etc etc.
I don't care about proving the site's identity; I just want to encrypt a password between clients and the server to protect from man-in-the-middle attacks)
That's exactly why you do care about proving the site's identity.
That in turn is why just using RSA without an authentication scheme isn't secure. It's no good having a secret conversation when you can't identify who you're talking to.
Is one more secure than the other?
id_rsa.pub and id_dsa.pub are the public keys for id_rsa and id_dsa.
If you are asking in relation to SSH, id_rsa is an RSA key and can be used with the SSH protocol 1 or 2, whereas id_dsa is a DSA key and can only be used with SSH protocol 2. Both are very secure, but DSA does seem to be the standard these days (assuming all your clients/servers support SSH 2).
Update: Since this was written DSA has been shown to be insecure. More information available in the answer below.
SSH uses public/private key pairs, so
id_rsa is your RSA private key (based on prime numbers), which is more secure than your id_dsa DSA private key (based on exponents). Keep your private keys safe and share your id_rsa.pub and id_dsa.pub public keys broadly.
DSA is insecure
DSA has a guessable parameter if your computer's random number generator is sub par, which will reveal your secret key. ECDSA (DSA's elliptical curve upgrade) is similarly vulnerable. Even with good random numbers, DSA has other strength concerns/🎬 (these are also found in Diffie-Hellman).
OpenSSH creates insecure 1024 bit keys(workaround) and now disables DSA by default.
Prefer Ed25519
Elliptic curve cryptography offers increased complexity with smaller key sizes. Ed25519 (based on the complexity of plane-modeled elliptical curves) is the preferred implementation due to its assumed lack of meddling (leaked documents show that the US NSA weakens crypto standards).
Ed25519 was introduced in OpenSSH 6.5 (2014-01-30) and GnuPG 2.1 (2014-11-06) and became the default ("first-preference") in OpenSSH 8.5 (2021-03-03). Older systems may not yet accept Ed25519, but the list of supported implementations has been growing steadily.
Use RSA with 4096 bits when Ed25519 is unavailable
RSA key sizes of 4096 bits should have comparable complexity to Ed25519.
Ed25519 is still preferred to RSA due to a worry that RSA may be vulnerable to the same strength concerns as DSA, though applying that exploit to RSA is expected to be considerably harder.
rsa is considered more secure.
Not anymore (May 2020, ten years later), with OpenSSH 8.2, as reported by Julio
Future deprecation notice
It is now possible1 to perform chosen-prefix attacks against the SHA-1 hash algorithm for less than USD$50K.
For this reason, we will be disabling the "ssh-rsa" public key signature algorithm that depends on SHA-1 by default in a near-future release.
(See "SHA-1 is a Shambles: First Chosen-Prefix Collision on SHA-1 and Application to the PGP Web of Trust" Leurent, G and Peyrin, T (2020) )
This algorithm is unfortunately still used widely despite the existence of better alternatives, being the only remaining public key signature algorithm specified by the original SSH RFCs.
The better alternatives include:
The RFC8332 RSA SHA-2 signature algorithms rsa-sha2-256/512.
These algorithms have the advantage of using the same key type as "ssh-rsa", but use the safe SHA-2 hash algorithms.
These have been supported since OpenSSH 7.2 and are already used by default if the client and server support them.
The ssh-ed25519 signature algorithm.
It has been supported in OpenSSH since release 6.5.
The RFC5656 ECDSA algorithms: ecdsa-sha2-nistp256/384/521.
These have been supported by OpenSSH since release 5.7.
To check whether a server is using the weak ssh-rsa public key algorithm for host authentication, try to connect to it after removing the ssh-rsa algorithm from ssh(1)'s allowed list:
ssh -oHostKeyAlgorithms=-ssh-rsa user#host
If the host key verification fails and no other supported host key types are available, the server software on that host should be upgraded.
A future release of OpenSSH will enable UpdateHostKeys by default to allow the client to automatically migrate to better algorithms.
Users may consider enabling this option manually.
Yes, rsa is considered more secure.
In October 2014, OpenSSH 7 (the default with Ubuntu 16.04LTS) has disabled default support for DSA. Take this as a strong sign that DSA is not a recommended method anymore.
https://www.gentoo.org/support/news-items/2015-08-13-openssh-weak-keys.html
One uses DSA and one uses RSA.