I am currently working on an Android app that talks to a server process on a remote machine. The installation packages for both the Android client and server need to be cryptographically signed; the Android client with a Java Keystore File (JKS) and the server with a PGP key from a keyring file. If possible, I would like to reduce the dependencies by signing both packages with the same key, but neither signing tool supports the opposite file format.
Is it possible to convert a PGP keyring file into a JKS file? Or alternatively, is it possible to convert a JKS file into a PGP keyring file? If so, how?
Edit for clarification: The idea here is to use a single cryptographic key as input for two different signing tools. The tools do not know about each other; it's just some random key to them. I do not want to sign an Android package with PGP, or the server installation package with Android's signing tool, as either would make the output unreadable to the end user.
While it might be theoretically possible there are certainly no tools to do that. If you would want to write one yourself there are a lot of hurdles to overcome. On a low level view there are many different ways to sign data (even if you restrict yourself to RSA, there are still many standards and parameters to choose from). On a high level view such key files and their front end abstractions of certificates or simply "keys" on the pgp side contain a lot meta information like a validity period, ownership information and so on. If you could actually deal with the low crypto problems then you still have to define some translation from one set of meta data to the other.
Also from a cryptographic point of view any key reuse is strongly frowned upon. There are many ways typically sound primitives can break apart if they are used in an unintended way. Certainly the authors and implementers of the algorithms behind the Android tools and the PGP tools did not imagine their tools to be used with such cross generated keys.
Related
Sometimes my Java program needs to send a .dll or .so file from client computer to remote machine. Is there a possibility to ensure that this .dll (.so) file is really created by me and not by some hacker? Firstly, I thought that digital signature (java.security package) would be my first choice, but I cannot verify signature in the remote machine, because Java may not be available there. Are there any other choices?
What you are trying to achieve is knowing as non repudiation. That is:
A service that provides proof of the integrity (nobody has modified your file) and origin of data (you are the genuine creator of the
file).
An authentication that can be asserted to be genuine with high assurance.
It's not about Java or C# or the language itself, it's a concept that doesn't depends on the programming language you are using.
Every language has it's own classes, libraries, mecanisms... for dealing with that, some in a better or easier way than others.
Specifically in Java, you can start taking a look here. The steps you need:
Generate a pair of keys (only done once).
Sign every document you create on client side (that ensures nobody can change it, nobody can take it's ownership and nobody can refuse the ownership of the file).
Send the document and it's signature.
On server side, verify the validity of the signature against the provided document.
If you only want to check if the file hasn't been modified you can use a simple digest mecanism without signing, just creating a hash (don't need to create certificates, validate signature...) and verify later will work, BUT be aware that with only hash, you can't check who is the author of the file, only that the file hasn't been modified since it's hash creation.
Is it possible that a file signed by GPG https://gpgtools.org/ can be verified using some other tool say BouncyCastle or GnuPG https://www.gnupg.org/? In my opinion it should not be because key providers are different. Am I right? I need some knowledge in this context. Please help.
Is it possible that a file signed by GPG https://gpgtools.org/ can be verified using some other tool say BountyCastle or GnuPG https://www.gnupg.org/?
Yes, of course! Both GnuPG and BouncyCastle implement the common standard OpenPGP. GPGTools just ships GnuPG as binary distribution and adds some tools.
In my opinion it should not be because key providers are different. Am I right?
There is no central trust entity like a certificate authority in OpenPGP, with other words no trusted keys are preconfigured.
To verify signatures, you need to fetch the matching public key. This will tell you, whether the signatures was issued by the matching private key and whether the file was tampered or not. It does not say anything on the validty of the key and signature; you have to verify the key on some other way. This might be by comparing the fingerprints manually, or using the OpenPGP web of trust to find a trust path from a trust anchor like your own key.
I need some knowledge in this context.
It looks you're still very new to those technologies. Covering them in depth is far beyond an answer on Stack Exchange. I'd strongly recommend to read up on the following topics, to get a feeling for the topics:
Public-key cryptography
PGP and OpenPGP
Public key infrastructure, especially the Web of trust in contrast to the Certificate authority system
I'm looking for a way to digitally sign a shared library so I can verify the authenticity of said library. My proposed solution was to hash the library and store this in the Java file that loads and calls the library but the problem is that this will fail if the library is updated in the future (unless all applications using the library are also updated).
I was thinking it might be possible to instead insert a hash of the library that has been signed with a private key to, for example, the end of the .so file so that this signed hash can be trusted and does not need to be stored in the calling application for verification. Is there any support for this in the Android APIs and will inserting data into the library in this way potentially cause problems for the library loader?
If your library is not being installed in /system/lib, it is normally used by one application - the one which had the library packed into its APK, and the typical update process will involve both the C++ library and the Java app. Therefore your verification does not need to survive updates.
On the other hand, the standard authentication techniques apply to library signing as well. E.g. add a new API "GetVersion(int salt)" which will return the shared secret (which may be the hash of the same file), "salted" with the random input. Now, you make reverse engineering your signature harder, because no man-in-the-middle analysis cannot give them a clue.
This may be easier to implement than looking for a signature at fixed offset of the library file, and harder to work around.
At any rate, appending an arbitrary blob at the end of a shared object will not cause problems with the loader. You can add the custom step of modifying the .so files in your Android.mk files. You must do it during or after the install step, which strips the debug info from the library.
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'm thinking about encryption in an application. The architecture consists of:
Server
Desktop client
Web client
mobile client
The goal is to allow user to store his data on the server, and access it from all clients, but to guarantee data privacy by encrypting data on the client.
Dropbox is an example of such an architecture, but as far as I know they don't do that - they must store plaintext data on their servers, otherwise they wouldn't be able to save on space by storing the same file only once, even if it was stored by multiple users.
How would you implement such an application? I'm thinking about using Java for desktop client; the same encryption code could theoretically be reused in GWT web client (compiled to Javascript) and in Android client. However, that's only in theory.
Is there an encryption library that's available on all these platforms?
What algorithms to use?
What about private keys? I can ask user for the password every time, but how do I ensure that private keys are the same for the same user in all clients?
I'd like to avoid multiple passwords; but if I use the same password for both data and authentication, how do I prevent server from giving data to a hacker which supplied the wrong password, or server from being able to decrypt user data because it has user's password?
What possible gotchas are there?
You actually need a few different pieces of cryto.
First, you want the client to encrypt the file for upload, and upon retrieving the encrypted payload back decrypt it.
Second, you want some method to transmitting the encrypted file for upload in a manner that insures that only the correct user can access his files.
The first problem requires a symmetric encryption algorithm. There are a bunch out there, but your best bet is probably AES. If you take a look at gwt-crypto at they have a wrapper for the java bouncy castle implementation. That takes care of two of three of your platforms. I don't work with android platform, but I'd be surprised if there wasn't an AES implementation floating around. As for the key, you'll probably end up with a hash of a password. Just keep in mind the possibility of rainbow tables and take appropriate measures. The password used to encrypt the file need never go over the wire, as I understand your model all encryption and deception is done on the client. Since you mentioned system administrators as a potential attacker, you really need to look into key loggers, memory dumps and the like, but that's beyond the scope of the specific question you asked.
The second problem is a solved problem using TLS with client and server side certificates. Clients for such are available for all three platforms you are looking at. Whether you want make your users go through the hassle of installing client side certificates, though, is up to you. There are various fallback options but none are as well vetted.