Public Key signing/verification - public-key-encryption

I'm developing an application to manage file and email encryption using (primarily) PKI. I have a Public Keyring with a list of contacts and their Public Keys.
Referring back to the olden days when I used PGP, I recall a requirement to sign public keys with your Private Key.
Is this a necessity on PKI and if so, what does this signing achieve? Is it bad practice to simply hold a list/database of people's names (and email) and their Public Key? Surely if their public key is - in any way - tampered with the encryption would fail and as you choose who you're sending or sharing the encrypted data with, even if a 'successful tamper' went unnoticed, the encrypted data wouldn't end up in the wrong hands anyway?

The whole thing about signing a public key with a private key is useful when you have a dedicated key-pair that you use only for signing, and then other key-pairs that you use for encrypting. This dedicated key-pair is your "trusted" key-pair that is somehow known to be legitimately attached to you (often by having it signed by a certificate authority or by having many trusted people sign that they have verified it's connection to you.)
You use this "trusted" private key to sign your not-quite-as-trusted public key. This way, people can un-sign/decrypt your new public-key with your trusted public-key. This is only mathematically possible if it was signed by your trusted private-key.
This process helps people to be sure that this new public-key actually belongs to you.

Related

Offline check a token's validity against user alteration

I have a question about protecting data against an untrusted end-user in the following scenario:
Basic feature to implement:
User logs into desktop app using username and password in order to have access to a subscription based software
The server respond with an encrypted token having a validity (30 days for example) and a Hardware Identifier specific for that one machine for which the user is now entitled. The server also responds with a public key with which the token above can be decrypted/checked
Every time the user launch the desktop app, if we are in an offline scenario we check the validity of the token by decrypting it with the public key, and then we can check if it is still within the validity period, and if it is on the correct Hardware as well (i.e. if the user did not just copy the encrypted files on a different machine and try to use the same account on more computers simultaneously)
Problem:
The scenario above has no protection against an untrusted user.
Example of possible attack:
The user decrypts the token using the public key
He now edits the token and sets a new Hardware Identifier, for the new machine he wants to copy the tokens
He edits the expiring date to 31.12.2099 for example
He generates his own private-public pair of keys
He encrypt the token again with his own private key
Now he can transport the encrypted token together with his own public key on the new machine, and as soon as he launches the desktop app in an offline scenario, the app has no way to tell that the token has been altered. It checks the authenticity of the token, but it can't check that the public key has been corrupted as well.
Every asymmetric encryption approach assumes that the end-user is trustable. For example when signing an app with a certificate, we assume that the user has no intention in attacking the offline trusted root certificates.
A solution I avoid would be to encrypt the private key or the public key within the code, but:
That is very very unsafe
That is not flexible in case you want to update the keys
It can be reversed engineered
After studying cryptography for a while I never realized that this scenario is so unsafe. Now I am wondering how a lot of already existing apps work in this scenario without exposing themselves to this so easy attack?
Thank you!

Detect the existence of a private key

I 'm trying to present the user a dialog to pick a certificate. Originally I used CryptUIDlgSelectCertificateFromStore with the "MY" store, but this results in picking all the certificates, where I only want the user to select between the
certificates that have private keys.
For that reason, I create a new memory store and store only the certificates for which a private key exists. I can use CryptAcquireCertificatePrivateKey to get a private key of a certificate, but this may result in a dialog box requesting a PIN for example. I don't want to use the CRYPT_ACQUIRE_SILENT_FLAG because a provider might want to show information on the key (not necessarily a pin or a smart card prompt).
Is there a way to know that there is a private key without actually acquiring it?
Thanks.

How to change the owner name in a Google Play signing key?

I know that some things in a signing key (like the validity period) can't be changed. Can the owner name change? If yes, how can I do it using keytool?
Interesting question. I've done a bit of digging, and it seems like it isn't possible. See this detailed answer on the security stack exchange. While you (and I) often think of certificate as just a public key, the certificate is the public key combined with the owner (Distinguished-Name) information, and the certificate hash is a hash of this information. So if you change the Owner information, you change the certificate, and so change the certificate hash. This is true for both APK Signing V1 and V2.

Is it secure mechanism of sharing data?

I need to share a file with some users. Using the way described below. Is it secure to share keys?
I have a data file.
I will encrypt a file, using any algorithm(GPG, OpenSSL).
Before encrypt I create keys private and public.
Then I upload a file to public storage.
If someone will find a file, and download it, he couldn't read encrypted file.
If I share my keys (private or public key?) with someone whom I want to share, he could decrypt use the same algorithm with my key.
Is it secure to share a key to decrypt a file?
If you wanted to share an encrypted file with someone, that intended recipient would give you their public key. You would encrypt it with the recipient's public key and only the recipient would be able to decrypt it with their private key.
Generally, no, it is not secure to share a key.
Other things to consider:
Public/Private keys can only encrypt a small amount of data by themselves. Generally they are used to encrypt symmetric keys that are used to encrypt/decrypt the payload. Using GPG etc would likely generate a "file" for you that has the symmetric key encrypted with the recipient's public key as well as the symmetrically encrypted payload. The recipient decrypts with their private key.
When you get your intended recipient's public key, how can you be sure the public key came from your recipient? Read up on the concept of man-in-the-middle for some things to consider.

What is the process for signing code with a signing certificate?

I am a new developer working on an open source application and I am trying to figure out how one signs a program.
I understand why code signing is a thing, and I know how to get a certificate (from a CA or individually), but I can't find anything explaining the actual process of signing itself once you have your private key.
How does one sign code with a signing certificate? Specifically, do you sign the source code, the built executable, something else entirely? Do you run a specific app, or include something in the code?
related but discrete question: What to do with the code signing certificate?
You have a code signing certificate which contains a private key and a public key.
You calculate a cryptographically save checksum of your code and data, encrypt it with your private key. You add the encrypted checksum and your public key to your code.
Now anyone can calculate the same checksum of your code, decrypt the encrypted checksum with the public key, and compare them. If they match, then it is proven that the code was supplied by someone who has your private key. If they don't match, then it is proven that this code is not the same as the on of which you encrypted the checksum.
To be useful, the operating system would perform this kind of test before any application is allowed to run. And the public key would be signed with well known private key owned by the OS supplier, and would likely be accompanied by data that can be used to identify the owner of the public key.
Obviously EvilHacker could create malware and code sign it. So the fact that it is signed is meaningless. But you would also have the identity of EvilHacker, or the operating system wouldn't start the application. So the operating system will never allow you to run a hacked application or one where the owner of the public key is not known to the creator of the OS.
The second worst a hacker can do successfully is to completely remove the code signing and give you unsigned hacked code - the OS will likely ask you whether you want to run unsigned code or not, or not allow it at all.
The worst a hacker can do is either to con the os owner to accept EvilHacker's code signing certificate, or steal a code signing certificate and create malware that is actually correctly signed.

Resources