I am generating RSA signature using RSA_PKCS1_PSS_PADDING. I am setting digest algorithm as SHA256 using EVP_get_digestbyname() and EVP_DigestSignInit(). And salt length parameter as -1 using EVP_PKEY_CTX_set_rsa_pss_saltlen().
I have EVP_MD_CTX, EVP_MD and EVP_PKEY_CTX structures used for signature generation.
How can I get the name of Mask generation algorithm name used by OpenSSL by default? Is there any API provided for getting it?
Edit: OpenSSL version used: 1.1.0g.
RSASSA-PSS is in practice always used with MGF1 as the Mask Generation Function. The only variation is which Message Digest is used internally by MGF1.
Sometime that's the same Message Digest as the one used for hashing the message and building the tag in PSS, because that makes the most sense. Other times it is SHA-1 because that used to be the default MD for early RSASSA-PSS APIs, thus for the associated MGF1.
In an ideal world, some attribute (in the signature, or/and in the public key certificate used to check the signature) would tell MGF1-with-such-MD, perhaps by way of some Object IDentifier like we have to specify PSS. But crypto APIs are hell.
In order to control what Message Digest is used by MGF1, we want something on the tune of what -sigopt rsa_mgf1_md:sha256 does in the openssl dgst command.
My best guess is to set the MGF1 digest using
assert(EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, EVP_sha256)>=0);
or get it using EVP_PKEY_CTX_get_rsa_mgf1_md() as documented:
The EVP_PKEY_CTX_get_rsa_mgf1_md() macro gets the MGF1 digest for ctx. If not explicitly set the signing digest is used. The padding mode must have been set to RSA_PKCS1_OAEP_PADDING or RSA_PKCS1_PSS_PADDING.
Related
I will start with a disclaimer that I am out of my depth here. A colleague was showing me a decryption routine he wrote with pycryptodomex. He had an encrypted file, a key, and a nonce (extracted from the file). He was able to decrypt the file contents in a very straight forward way.
c = Crypto.Cipher.AES.new(key, AES.MODE_GCM, nonce)
c.decrypt(encrypted_data)
You can see a similar implementation in the pycryptodome test for GCM:
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
pt = get_tag_random("plaintext", 16 * 100)
ct = cipher.encrypt(pt)
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
pt2 = cipher.decrypt(ct)
Unfortunately, pycryptdomex is an additional dependency that I would need to carry around and I am looking to avoid this. I have a base installation of Anaconda, which brings with it the pyCrypto and pyCA/cryptography packages. It appears that pycryptodomex is a fork of pyCrytpo, which didn't have a stable GCM implementation to begin with. When I look at the implementation for PyCA/cryptography, it looks straight forward:
cipher = Cipher(algorithms.AES(key), modes.GCM(nonce), backend=default_backend())
d = cipher.decryptor()
But when we want to decrypt content we have to call finalize_with_tag and produce an authentication tag:
d.update(encrypted_data) + d.finalize_with_tag(tag)
Unfortunately, I don't have an authentication tag nor do I know where to find it. I can't set the value to None as there is a minimum length requirement. I'm also not sure why I need to produce an authentication tag in the first place for AES GCM decryption with PyCA/Cryptography but I do not need to produce a tag when decrypting with the pycryptodomex. I'm ultimately looking for clarity on the following:
Is it possible to implement AES/GCM decryption with the Anaconda PyCA/cryptography package if I only have access to the key, nonce, and encrypted data?
Why do I need to provide an authentication tag for decryption with one implementation and not the other?
Is pycryptodomex doing something under the hood to determine the tag?
GCM without authentication tag is equivalent to CTR mode. (except the + 1 difference in starting counter value)
Calling decrypt does not verify the tag (as far as I know). You can test this yourself by altering the ciphertext just one byte. It will decrypt just fine (to a plaintext that is off by one byte). Use decrypt_and_verify (see test_invalid_mac test).
See 2.
Apologies as I can't reply to comments. Is it possible to derive the tag from the decrypted data after decryption? This PR associated with PyCA/cryptography seems to imply the exact scenario considered here.
According to the GCM spec (section 7.2: “Algorithm for the
Authenticated Decryption Function”), the tag itself is not needed
until the ciphertext has been decrypted.
Does calling d.update(encrypted_data) decrypt data successfully and d.finalize() is only needed to verify the integrity of the data?
I would like to know which part does the RSA 1024 or AES 256 used inside tor?
Because I found many post saying about RSA or AES when discussing tor.
whenever I look for how tor works, I got the answer like it encrypted 3 times each layers, and decrypt once each node.
I want to know how it encrypt and what is the thing it encrypt in a real tor network.
A really simple example is fine. Thank you.
FYI tor.stackexchange is a better place for this. Also a warning, I know just enough to be dangerous :)
See https://gitweb.torproject.org/torspec.git/tree/tor-spec.txt section 0.3.
For a stream cipher, unless otherwise specified, we use 128-bit AES in counter mode, with an IV of all 0 bytes. (We also require AES256.)
For a public-key cipher, unless otherwise specified, we use RSA with 1024-bit keys and a fixed exponent of 65537. We use OAEP-MGF1 padding, with SHA-1 as its digest function.
v2 hidden services identity keys were RSA-1024, but the newer v3 onion services public keys use ed25519.
Every Tor relay's long term signing-only identity key is RSA-1024. Medium-term ntor "Onion Keys" are Curve25519. Long-term "master identity" keys (which never change for a given relay) are Ed25519.
The tor-spec document also describes the encryption that can be used for connections between two relays in section 2 (Connections):
Connections between two Tor relays, or between a client and a relay, use TLS/SSLv3 for link authentication and encryption. All implementations MUST support the SSLv3 ciphersuite "TLS_DHE_RSA_WITH_AES_128_CBC_SHA" if it is available. They SHOULD support better ciphersuites if available.
Section 2.1 goes on to say about picking TLS ciphersuites...
Clients SHOULD send a ciphersuite list chosen to emulate some popular web browser or other program common on the internet.
Because OpenSSL is used behind the scenes, all kinds of cipher suites are supported including things like TLS1_ECDHE_ECDSA_WITH_AES_256_CBC_SHA and TLS1_RSA_WITH_AES_128_SHA.
The materials in https://gitweb.torproject.org/torspec.git/tree/ will answer all of your questions.
Is there any way to verify the OpenSSL signature using only {signature,hashed message} pair, skipping the original file to be presented for verification?
I need to verify the signature with only {signature,hashed message} pair remotely so using the original file is cumbersome specially when its very large.
Is there any way to verify the OpenSSL signature using only hash value and without needing the original file?
Yes, but there are strings attached.
The scheme which requires the original message to be presented to the verifying function is a Signature Scheme with Appendix (SSA). A scheme like the old PKCS #1.0 signing is an example of it.
The scheme which does not require the original message is a Signature Scheme with Recovery (PSSR). In a PSSR, the encoded message is part of the signature and masked. A scheme like the new PKCS #2.0 PSSR signing is an example of it.
There are no schemes that take just a hash, as far as I know. You have to have the {message,signature} pair. Allowing the message to be disgorged from the signing or verification can be a security violation.
OpenSSL provides both of them, as does most other security libraries, like Botan, Crypto++, NSS, etc.
Also see RSA signature on TLS on Information Security Stack Exchange.
I have been trying to verify the signature with hash value remotely so using the original file is cumbersome specially when its very large.
That's the insecure thing signature schemes want to avoid....
Can anyone help with the code how to decrypt with private key ,As in server side they are using OAEP encryption method .I tried decrypting using private key but the decrypted text is Null,I am getting the Error code as -9809 as decryption code result
When you say "with a private key" I assume you mean you're using SecKeyDecrypt() for asymmetric encryption rather than CommonCryptor for symmetric encryption.
SecKeyDecrypt() does not support OAEP. It only supports PKCS1 v1.5 padding (kSecPaddingPKCS1). It can also technically handle ASN.1 padding + PKCS1 padding, but this isn't usually relevant to decryption. You should have noticed this when you passed the SecPadding parameter. What did you pass?
That error number is errSSLCrypto which is a generic "something went wrong in crypto" message.
I'm planning to use code similar to Amazon AWS samples to authenticate signed API requests. So users will have something like:
use Digest::SHA qw(hmac_sha256_base64);
my $digest = hmac_sha256_base64 ($request, $self->{SecretKey});
and attach $digest as a parameter to their request URI. The server-side will use the same algorithm to create a digest from the client URI and compare that to the value sent by the client.
What I can't find is Perl support for generating the SecretKey of the correct length to use when generating HMAC SHA256 digest.
For my Amazon AWS account I'm being given a 40 ASCII character base64 encoded string.
How do I generate a proper secret-key for my clients?
I suggest you use a PBKDF2 algorithm. PBKDF2 = "Password-based Key Derivation Function (#2)". It is defined in PKCS #5 (RFC 2898). This is the recommended way to derive a key from a password. You will need a salt, as well. A typical iteration count is 1000.
This page says it has a perl implementation of PBKDF2. I haven't tried it.
Apparently there is also a Crypto::PBKDF2, but it is saddled with dependencies you may not want.
EDIT
I just tried Anthony Thyssen's perl program for pbkdf2 - it works great. Simple, easy.