My application has to publish a file to several clients over a common channel. I have been doing below process to encrypt it
Generating a symmetric key to encrypt the data.
then encrypting this key with RSA public key and publish it.
Considering all the clients of this application have application's RSA public key, is there any standard format to encrypt a file before publishing it?
Apparently, there are several standard formats for encryption. One of the most popular standard format is Cryptographic Message Syntax (CMS). Also refer to specs for CMS at Internet Standard. This format is widely used for for S/MIME mail message security.
Bouncy Castle APIs provides a wonderful support for this. BC's bcmail-jdkNN-MMM.jar is the Bouncy Castle SMIME/CMS library which is of your use. It is a package for processing RFC 3852 Cryptographic Message Syntax (CMS) objects - also referred to as PKCS#7 (formerly RFC 2630, 3369), and also dealing with S/MIME objects (RFC 3851).
Another popular standard format, XML Encryption format. end-to-end security for applications that require secure exchange of structured data. XML itself is the most popular technology for structuring data, and therefore XML-based encryption is the natural way to handle complex requirements for security in data interchange applications.
Related
Is there any way to make XAdES signature using Google Cloud KMS? I cannot find any info about it.
Wow, XAdES is a maze of twisty standards documents, it's tough to find what is supported. From what I can tell, XMLDSIG originally supported DSA and RSA-SHA1 which are now pretty dated and neither is supported by Cloud KMS's algorithms.
In 2013 XML Signature Syntax and Processing Version 1.1 which specified some more algorithms, including an RSA algorithm with SHA-256 which should be compatible with Cloud KMS's RSA_SIGN_PKCS1_2048_SHA256, RSA_SIGN_PKCS1_3072_SHA256 and RSA_SIGN_PKCS1_4096_SHA256. and I believe its ECDSAwithSHA384 should be compatible with Cloud KMS's EC_SIGN_P384_SHA384.
There may have been further developments since then with other supported algorithms. I suspect that particular XAdES implementations or interoperability groups may only support a selection of algorithms, so you may need to check with those for interoperable algorithms.
All that said, Cloud KMS does not provide the tooling to encode the documents for signing nor encode the signatures in a way compatible with XAdES, so while I believe, if you had algorithmic compatibility, you could implement signing with keys stored in Cloud KMS, but it would take a chunk of work to do the various format conversions.
Thanks for using GCP and Cloud KMS. If you have more info on what you wish it could do, I'd be happy to get the request.
I'm creating a web service that stores a list of users with their public keys online, as well as encrypted messages. My end goal was end-to-end encryption.
I initially thought this would be pretty easy -- "Oh, OpenSSL and RSA private/public key asymmetric encryption is great." False. RSA will only encrypt a tiny bit of data, presumably to pass a regular, symmetric key back and forth.
Okay, so I tried to find solutions online. Most of them either ended without a functioning example or pointed at using the command line, all of which seemed excessive and incomplete.
Is there a way to use end-to-end encryption on data with asymmetric keys, or is it all a personal pipe dream? OpenSSL in PHP has a way to do this already, and it's kludgy but it works.
Is there some method I'm missing here?
The common way to encrypt larger amount of data with a asymmetric keys (eg. RSA) is by use of hybrid encryption. In hybrid encryption you mix symmetric and asymmetric encryption. First you generated a random symmetric key, that is used to encrypt the data. Then you encrypt the symmetric key with the asymmetric key. The encrypted data + the encrypted random key are then put together and makes up the full encrypted data.
The openssl_seal() in PHP you refer to, uses hybrid encryption where the symmetric algorithm is RC4. How data is encoded and put together in the encrypted files have been defined by the openssl implementation, and might not necessarily be the way you would want to do it. PGP, as an other example of hybrid encryption, uses it's own way of packing the data.
In any case, hybrid encryption is not something you get out of the box in java, and you typically need to implement each of the encryption + packaging steps yourself, or use one of the libraries that implements there version of this. An example of doing it yourself is this Java code I found that can decrypt messages encrypted with the above mentioned openssl_seal().
An example of using a library for hybrid encryption, could be using the PGP support in Bouncy Castle.
Ebbe's answer is very good, however this question was highly ranked in Google in my attempt to try and find a decent hybrid encryption library (Bouncy Castle's documentation is non-existent and not straight-forward, and GnuPG for Java relies on the OS and is not fully tested). So I thought I'd add on to Ebbe's answer for the weary traveller.
If you can use them, JWTs (JavaScript Web Tokens) could be handy for this. It's also an IETF Standard. There are two different types:
JWS, which is a signed JWT. Plain-text message, but you can verify its authenticity. Which has its own IETF Standard
JWE, which is an encrypted JWT. Which also has its own IETF Standard
Support for JWEs are unfortunately a bit poor at this point in time. However this should hopefully improve. At this point in time (2017-04-11), the only Java JWT library that supports JWEs is BitBucket's Jose4j.
I'm not really sure what you're trying to en- and decrypt, but GnuPG for Java might be a good choice.
It supports public and private keys and can en- and decrypt bigger files and data.
I have just watched a crypto 101 talk which said if you are typing the letters "AES" into your code, you're doing it wrong! The solution was to "just use GPG".
If you are storing your data on the cloud, all readers and writers need to know the key. If the key is a public private key, that's just a slow key but not a more secure key than just having a good password?
What standard alternatives are there to GPG that properly encrypt data at rest but use a shared secret instead of public keys?
I use Java, and would like to use a library, but want interchange with other platforms.
The solution is wrong in terms - you don't use "GPG" but OpenPGP.
Indeed for encryption using shared secrets (passphrases and alike) OpenPGP is optimal, as it supports multiple methods at the same time and includes compression.
The alternative would be to use CMS encryption with keypairs derived (in some predetermined way) from the shared secret. However such scheme is not standard.
I can remember also XML encryption that supports encryption with symmetric keys, but it has certain security flaws.
So OpenPGP is probably the best way to go.
Regarding compatibility - OpenPGP-compliant library should create packets that can be later processed by any other OpenPGP-compliant library or application. Unfortunately OpenPGP implementation in popular BouncyCastle library sometimes produces not compliant packets - we came across its issues several times when packets created with BouncyCastle could not be processed by GnuPG or our SecureBlackbox due to issues in the packet created.
I am currently upgrading an application that generates OpenPGP messages to be FIPS 140-2 compliant. Currently I generate PGP messages that use RSA/AES-256 encryption which are both approved algorithms using BouncyCastle and its OpenPGP provider. I am no longer able to use BouncyCastly since it is not FIPS 140-2 validates, so I am looking at the BSAFE library from RSA.
This library doesn't have the high-level abstraction to let you generate an OpenPGP message directly. Does anyone know of a library that can use an existing JCE provider (like my BSAFE library) capable of generating OpenPGP messages? I'd really like to avoid having to implement the OpenPGP spec myself, as that seems like it would be quite time consuming. Alternatively any suggestions for other ways to format my encrypted files?
Thanks in advance for any input!
After much research it seems that there is no way to do this without implementing the OpenPGP format yourself. However the Cryptographic Message Syntax seems to be a suitable replacement.
There are major differences between S/MIME (Cryptographic Message Syntax) and OpenPGP.
http://mozilla-enigmail.org/forum/viewtopic.php?t=67
Mainly, S/MIME exchanges keys in terms of certificates (which must utilize a certificate authority, limited to 1024 bit, and expires after 1 year), while OpenPGP uses PGP keys (can be exchanged peer-to-peer, or utilize a free keyserver, or host your own keyserver).
FIPS 140-2 doesn't apply to protocols like SSL, PGP, S/MIME, or SSH. Those are security protocols that use cryptographic algorithms like RSA and AES. (Commercial crypto vendors aren't likely to point out this distinction, however).
FIPS 140-2 lists approved algorithms. It also specifies testing criteria for "cryptographic modules" that implement these algorithms. But, it doesn't say anything about the application of these algorithms.
So, you can use BouncyCastle's PGP provider. Instead of installing Bouncy Castle as a crypto-provider, install your FIPS 140-2–certified implementation. Bouncy Castle's PGP will use the preferred crypto provider for its underlying cryptographic algorithms. You can use their S/MIME support in the same way.
I need encrypt data using exactly the PKCS#1 V2.0 encryption method (defined in item 7.2.1 of the PKCS#1V2 specification).
Is it already implemented for Java?
I'm thinking in something like just pass a parameter to javax.crypto.Cipher specifying "PKCS#1V2", I wonder if there is something like this?
PKCS#1 v2.0 encryption is usually called OAEP encryption. So:
Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");
The place to look is the Java Cryptography Architecture documents: Standard Algorithm Name Documentation or Sun Providers Documentation.
As you can see the SunJCE provider supports the following variations of OAEP:
OAEPWITHMD5ANDMGF1PADDING
OAEPWITHSHA1ANDMGF1PADDING
(OAEPWITHSHA-1ANDMGF1PADDING)
OAEPWITHSHA-256ANDMGF1PADDING
OAEPWITHSHA-384ANDMGF1PADDING
OAEPWITHSHA-512ANDMGF1PADDING