I am currently trying to build a project (self-learning) which essentially is a website for sharing files (between two users). I want to encrypt a file (pdf) using ECIES (primary objective) and then send it to another user. My questions are:
How to encrypt a file at client-side?
How to send an encrypted file to a server (which language/library/technology)
As my questions suggest, I am a beginner in web development.
As you're probably already aware, you won't get much use on a website like that as it's really difficult to prove you're not performing a MITM attack. That said from a cryptography point of view the tech you should use/investigate is:
ephemeral:ephemeral elliptic curve Diffie-Hellman, using a strong curve with fast, constant time scalar multiplication such as curve25519/x25519, deriving a shared secret which can be used (by hashing the x co-ordinate with a strong hash function such as SHA-256, SHA-3 or Blake2b).
using the key agreed in step one, encrypt with a strong authenticated symmetric cipher such as ChaCha20-Poly1305.
There are tonnes and tonnes of options, perhaps if you wanted to try being decentralised, the website could help route users to each others public keys on IPFS.
Related
What is the most secure hash algorithm to use in ColdFusion 9 (non-Enterprise)?
According to the CF documentation, these are the options:
MD5: (default) Generates a 32-character, hexadecimal string, using the
MD5 algorithm (The algorithm used in ColdFusion MX and prior
releases).
SHA: Generates a 40-character string using the Secure Hash Standard
SHA-1 algorithm specified by Nation Institute of Standards and
Technology (NIST) FIPS-180-2.
SHA-256: Generates a 44-character string using the SHA-256 algorithm
specified by FIPS-180-2.
SHA-384: Generates a 64-character string using the SHA-384 algorithm
specified by FIPS-180-2.
SHA-512: Generates an 128-character string using the SHA-1 algorithm
specified by FIPS-180-2.
But in this article, it says not to use MD5 or SHA-1
I am also a little skeptical about the cf documentation. It says encoding "SHA-512" uses SHA-1, but the description of "SHA-512" for the Enterprise version is "The 512-bit secure hash algorithm defined by FIPS 180-2 and FIPS 198." And the output of SHA-512 is larger than SHA-384. Sorry, I am having a hard time getting my head around all these different encoding principles.
Hashes are not secure by themselves, anything that can be hashed can be broken. So in the security world you might think, ok I need to run the hash multiple times to obscure it more, but that doesn't secure the information, it just means someone has to repeat that same process and iterate over the hash multiple times. If they know the hash algorithm you used and assume they do, it's not secure. Sha-256 should be good enough for hashing information unless you are trying to secure the information. Hashes should never ever be used by themselves to secure information. Just because it isn't human readable does not make it secure.
If you want to secure something use coldfusion a encrypt functions and make sure you use a decent algorithm, like AES because the default in coldfusion is not secure. Then you need to use some entropic data from the information you're securing to ensure you have a unique encryption key that would be hard for someone to guess or find. Do not hard code a single key in your code, this will make it easy for someone to find and utilize a pattern in all of your encryptions.
Use something like bcrypt or scyrpt for storing passwords. I know they are more work to put into use and require java integration in coldfusion but they are much more secure ways of storing information. Remember that even with bcrypt or scrypt the information can be compromised given enough time and someone willing to put the effort into decrypting it. Be paranoid when securing information.
Is there a way to setup a hierarchical encryption using public key encryption ?
Let's say a higher level user can decrypt messages encrypted by lower level users.
Is it something possible ? I guess it is only possible to do with hierarchical
key management, like the higher level users have access to the lower level user's keys.
Any other option to do something like this ?
What I'd propose is, to some extent, an extension of your hierarchical key management idea.
Here's the core idea:
We use a cryptographically-strong random secret to encrypt the file symetrically (public-key-encryption of large datasets is actually quite slow, so most software like GPG uses a symmetric block cipher to encrypt the data, then they public-key-encrypt the random secret.). The random secret itself is encrypted with the key of each user that is allowed to access the data.
This scheme is similar to when you send a PGP message to multiple receivers. It's quite simple, but the problem is you have to update any encrypted data if users are added, modified or removed. Generally you can introduce intermediary keys to counteract this effect.
In order to address these issues, cryptographers invented HIBE (Hierarchical Identity-Based Encryption). If you want to use this in a real application, please don't build the crypto stack yourself, but use proven, peer-reviewed algorithms.
I have made a small program that will allow me to send licenses in encrypted form to users.
At the moment I have
An RSA private key that encrypts my AES key
A single AES/CBC key that encrypts the data
An RSA public key
Both the AES and public key are hard coded onto the device.
How should I deal with the IV when a license is requested, should I create a static one on the device or send a new one with every new license I create?
If I understand what you are trying to do then, like most licensing schemes, it is basically a DRM scheme. I'll only address the cryptography problem, but there is also of course the problem of playing hide-and-seek from the hackers. You should know that no DRM scheme offers any measurable security (unless perhaps security hardware is involved) in the cryptographic sense, but they are still common and some developers are comfortable with the logic behind them.
What you want to do is generate your license data and include some information that prevents a user from simply copying a valid license file from a legitimate user. Examples might be mac address, phone number, etc. Then you sign this data. The license then consists of the unencrypted license and the signature bytes. On the user side, your installation software will verify the signature using the hard-coded public key, and perform any other checks (mac address matches, phone number matches, etc).
This would be the core of your scheme, and is enough for most developers. You can take this core and further obfuscate it using ad-hoc including encryption, splitting, etc., depending on how far you want to go with the hide-and-seek game.
EDIT:
If I may make a suggestion, I think the book Beginning Cryptography With Java would be a wise investment. It includes examples that using the Bouncycastle library. You can donwload the examples for free from the same website.
Isn't this proposal totally silly?
You should encrypt with RSA public keys not with a private key. If you encrypt with a private key as you propose then everyone with access to the public key will learn the AES key and will be able to decrypt or forge anything. Of course for the same reason you should also not use the same AES key for distinct receivers.
And to answer the question, you should use a new random IV for each AES/CBC encryption.
A few years ago, when first being introduced to ASP.net and the .NET Framework, I built a very simple online file storage system.
This system used Rijndael encryption for storing the files encrypted on the server's hard drive, and an HttpHandler to decrypt and send those files to the client.
Being one of my first project with ASP.net and databases, not understanding much about how the whole thing works (as well as falling to the same trap described by Jeff Atwood on this subject), I decided to store freshly generated keys and IVs together with each file entry in the database.
To make things a bit clearer, encryption was only to protect files from direct access to the server, and keys were not generated by user-entered passwords.
My question is, assuming I don't want to keep one key for all files, how should I store encryption keys for best security? What is considered best practice? (i.e: On a different server, on a plain-text file, encrypted).
Also, what is the initialization vector used for in this type of encryption algorithm? Should it be constant in a system?
Keys should be protected and kept secret, simple as that. The implementation is not. Key Management Systems get sold for large amounts of money by trusted vendors because solving the problem is hard.
You certainly don't want to use the same key for each user, the more a key is used the "easier" it comes to break it, or at least have some information leaks. AES is a block cipher, it splits the data into blocks and feeds the results of the last block encryption into the next block. An initialization vector is the initial feed into the algorithm, because at the starting point there is nothing to start with. Using random IVs with the same key lowers the risk of information leaks - it should be different for every single piece of data encrypted.
How you store the keys depends on how your system is architected. I've just finished a KMS where the keys are kept away from the main system and functions to encrypt and decrypt are exposed via WCF. You send in plain text and get a reference to a key and the ciphered text back - that way the KMS is responsible for all cryptography in the system. This may be overkill in your case. If the user enters a password into your system then you could use that to generate a key pair. This keypair could then be used to encrypt a key store for that user - XML, SQL, whatever, and used to decrypt each key which is used to protect data.
Without knowing more about how your system is configured, or it's purpose it's hard to recommend anything other than "Keys must be protected, keys and IVs must not be reused."
There's a very good article on this one at http://web.archive.org/web/20121017062956/http://www.di-mgt.com.au/cryptoCreditcard.html which covers the both the IV and salting issues and the problems with ECB referred to above.
It still doesn't quite cover "where do I store the key", admittedly, but after reading and digesting it, it won't be a huge leap to a solution hopefully....
As a pretty good soltution, you could store your Key/IV pair in a table:
ID Key IV
skjsh-38798-1298-hjj FHDJK398720== HFkjdf87923==
When you save an encrypted value, save the ID and a random Salt value along with it.
Then, when you need to decrypt the value, lookup the key/iv pair using the id and the salt stored with the data.
You'd want to make sure you have a good security model around the key storage. If you went with SQL server, don't grant SELECT rights to the user that accesses the database from the application. You wouldn't want to give someone access to the whole table.
What if, you simply just generated a key for each user, then encrypted it with a "master key"? Then, make sure to have random ivs and as long as you keep the master key secret, no one should be able to make much use of any amount of keys. Of course, the encryption and decryption functions would have to be server-side, as well as the master key not being exposed at all, not even to the rest of the server. This would be a decent way to go about it, but obviously, there are some issues, namely, if you have stored your master key unsafely, well there goes your security. Of course, you could encrypt the master key, but then your just kicking the can down the road. Maybe, you could have an AES key, encrypted with a RSA key, and the RSA key is then secured by a secret passprase. This would mitigate the problem, as if you have a decent sized RSA key, you should be good, and then you could expose the encryption functions to the client (though still probably shouldn't) and since the key encryption uses a public key, you can have that taken. For added security, you could cycle the RSA key every few months or even weeks if need be. These are just a few ideas, and I know that it isn't bulletproof, but is more secure than just stuffing it in a sql database.
Say you have a bunch of files.
Say you can store meta data to these files.
Say, one of these meta attributes were called "encryption"
Say everyone was allowed to look at these files, but since they are encrypted, only people who know how to decrypt them can actually read the contents.
Say, for every given value of "encryption", a group of people share the knowledge on how to decrypt files marked with that value.
Say you want to be able to do this programmatically, in an OS agnostic way (if possible)
What are the values you would use for "encryption"?
How would you store the keys?
How would you organize access to the keys?
I am currently leaning towards following implementation:
the value of the field "encryption" contains the name of a key, possibly also denoting the algorithm used
each user has access to a bunch of keys. This could be defined by roles the user has in an LDAP/ActiveDirectory like structure, or they could just be files in a secure directory in the users profile/home directory.
on viewing a file, the viewer (I'm trying to build a document management system) checks the users keys and decrypts the file if a matching key was found.
What encryption would you use? Symmetric (AES)? Or Asymmetric (what are the good ones)?
Using asymmetric keys would have the additional benefit of making a difference between reading a file and writing a file: Access to the private key is necessary for writing the file, access to the public key (only semi public, as only certain roles have access to it) would allow reading the file. Am I totally mistaken here?
What are common systems to solve these problems used in small to medium sized businesses?
EDIT: It seems there are no universal sollutions. So, I will state the problem I am trying to solve a little more clearly:
Imagine a Document Management System that operates in a distributed fashion: Each document is copied to various nodes in a (company controlled, private) P2P network. An algorithm for assuring redundancy of documents is used to ensure backups of all documents (including revisions). This system works as a service / daemon in the background and shovels documents to and fro.
This means, that users will end up with documents probably not meant for them to see on their local workstation (a company controlled PC or a laptop or something - the setting is such that a SME IT guy sets this all up and controls who is part of the P2P network).
This rules out directory access based schemes, as the user will probably be able to get to the data. Am I mistaken here? Could a local folder be encrypted such that it can only be accessed by a Domain user? How secure is that?
I am aware of users sharing decrypted versions of files - and that that is hard to suppress technically. This is not a problem I am trying to solve.
The encryption isn't the hard part, here. Understanding the business needs, and especially, what threats you're trying to protect against, is the hard part. Key management isn't a trivial thing.
I highly recommend the book "Applied Cryptography" to help you understand the protocol-level issues better.
This is a hard problem. If this is something really serious, you should not use the advice of amateur cryptographers on the internet.
That said, here's my musings:
I'd encrypt each file with a random symmetric key using AES. This encryption would be on a job that runs overnight, so the key changes overnight.
I'd encrypt the key of each file with the public key of everyone who has access to the file.
If someone loses access to files, they'd be unable to read the new copies the next day (they could still have copies locally of old versions).
I'd use gpg (runs on nearly all OS-es happily).
You misunderstand asymmetric crypto. Public key is given to everyone, Private key you keep yourself. If Alice encrypts something with Bob's Public key, only Bob can decrypt it. If Bob encrypts something with his Private key - everyone can decrypt it, and everyone knows it came from Bob cause only he has his Private Key.
EDIT: However, if you ignored everything I said and went a different route, and gave every FILE it's own pub/priv keypair... then you would rely on the public key be available ONLY to those you want to read the file, and the private key available to those you want to r/w. But that's a bit trickier, and relies heavily on people not being able to distribute keys. Overnight jobs to change keys could mitigate that problem, but then you have the problem of distributing new keys to users.
If I understand you correctly, you could use GNU Privacy Guard. It's cross-platform and open source. Basically, every user has a copy of GPG and a local "keychain" with their "private keys" and "public keys". When you want to encrypt something, you use the person's public key, and the results can only be decrypted with their associated private key. A user can have more than one keypair, so you could give all administrators access to the "administrator role" private key, and each hold of they private key could decrypt documents encrypted with the "administrator role" public key.
The cool part is that you can encrypt a file with multiple public keys, and any one of the corresponding private keys could then be used to decrypt it.
The difficulty of this problem is why many businesses default to using OS-specific solutions, such as Active Directory.
For OS-agnostic, you have to re-create a lot of user-management stuff that the specific OS and/or Network vendors have already built.
But it can be done. For the encryption itself - go with AviewAnew's answer.
I have to agree with Mark here:
Understanding the business needs, and especially, what threats you're trying to protect against, is the hard part
For example; are you worried that unauthorized users may gain access to sensitive files? You can use file-level access control on virtually any operating system to restrict users or groups from accessing files/directories.
Are you worried that authorized users may copy the files locally and then lose their laptop? There are a number of os-level encryption facilities that provide varying degrees of protection. I personally recommend TrueCrypt for thumb drives and other portable media, and Windows Vista now include BitLocker which provides a different level of protection.
Another variation of the lost-laptop theme is the lost-backup theme, and many backup vendors now include encryption schemes for your tape backups for just this reason.
Finally, if you're worried that authorized users may share the files with unauthorized users then you may be trying to solve the wrong problem. Authorized users who can decrypt these files can just as easily share a new unencrypted version of the same document.
What you need is public-key encryption using either OpenPGP or X.509 certificates. In both cases you can encrypt the single block of data for multiple "recipients" using their OpenPGP keys or X.509 certificates respectively. In X.509 the standards for encrypting the data this way are PKCS#7 and CMS (defined in some RFC, I forgot the number). You would need to employ some key revocation checking in order to prevent access for those people, who were given access before but don't have it now.