I have chanced upon this wonderful library for java nimbus-JOSE for the use of JSON Web Encryption. This library is simple and requires few lines for JWE encryption and decryption like below shows JWE Encryption.
EncryptedJWT jwt = new EncryptedJWT(header, builder.build());
RSAEncrypter encrypter = new RSAEncrypter((RSAPublicKey) keyProvider.getDefaultPublicKey());
try {
jwt.encrypt(encrypter);
} catch (JOSEException e) {
throw new RuntimeException("Failed to generate encrypted token", e);
return jwt.serialize();
However, I had some questions regarding this library even after reading its javadocs and documentation. With respect to JWE and this library specifically,
After decrypting the JWE, how does one validate the authenticity of the JWE? There are no "signatures" in a JWE, so how does the 5 parts of the JWE help to check for validity? Is there any support for this in the library?
Other than the header and the claims, are the other fields in the JWT randomly generated by the library? (I was not able to find clear evidence of this.)
If I use alg: "RSA-OAEP", enc: "A128GCM", I should be getting a different JWE everytime i encrypt, however, I have been getting the same JWE. Shouldn't RSA-OEAP-256 prevent this from happening? What is the detailed sequence of encryption and decryption flow?
I have been trying to find a similar library in Javascript but was unable to find one like nimbus-jose which was for java. If anyone has a recommendation please do help below!
I would like to thank anyone who can help with my queries. All inputs are welcomed. :)
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?
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....
I have been attempting to put together a Scala library for making calls to Chef APIs but I keep getting this problem with authenticating the API calls.
I have triple checked and the private key is correct and all other headers. The code I am using is here:
https://github.com/LiamHaworth/shef/blob/master/src/main/scala/au/id/haworth/shef/ChefUtils.scala
and I am calling it like so
import au.id.haworth.shef.{RequestMethod, ChefUtils}
import au.id.haworth.shef.ChefServer
val key = io.Source.fromFile("user.pem").getLines.mkString("\n")
val chefServer = ChefServer("chef.example.com", 443, "https", "myorg", "myuser", key)
ChefUtils.sendRequestToServer(chefServer, RequestMethod.GET, "", "")
But I keep on getting this response from the server
"{"error":["Invalid signature for user or client 'myuser'"]}"
I am sure that the problem is simple and is staring me in the face but I can't see it so any help will be greatly appreciated
I have successfully got the API to authenticate. After using knife in debug mode to check what headers it was producing and adding a extra line into my mixlib to print the canonical headers I got it working.
With the canonical headers printed by mixlib I ran them through my signing code and found that I wasn't getting the same result with the signature so I dug a bit deeper to find I was signing my headers in the terribly wrong way.
I was digesting them not signing them! After swapping out RSADigestSigner for Signature in my code and changing the algorithm (SHA1withRSA to RSA) I finally got the headers to be signed the same as the mixlib ones!.
TL;DR I derped and used the wrong classes to do what I wanted to do. The changes I made can be seen in this commit:
https://github.com/LiamHaworth/shef/commit/2db2aa5b89cae272eecd0901be91533b61d2a6c3
I realize that there are a lot of similar questions to the one I am about to ask already on Stack Overflow, but none of them have clear answers that really satisfy my needs, so here we go:
My program receives an ASN.1 encoded RSA public key over the network. I have the data stored in a simple NSData instance. I wish to use that public key to encode 16 bytes of data and return those over the network. From my research the best way to do this seems to be to use a SecKeyRef. According to the ridiculously vague documentation provided by Apple this can be done using some code. However, their code presents a problem. Every time I want to use a public key I need to add it to the keychain and give it a unique identifier. The problem with this is that this key is to be used only once. I am looking for a way to obtain a SecKeyRef for a key that is not in the keychain and is created from an ASN.1 encoded key.
I have also considered the possibility of converting it to common PEM by base64-encoding and wrapping it in '-----BEGIN PUBLIC KEY-----' and '-----END PUBLIC KEY-----' and then loading it into a SecKeyRef, but I haven't seen a way to do this either.
Also, I don't have much of a choice in the type of key, key format, etc. Its from a 3rd party java server. Yay.
I currently have this alternate method of loading keys that (maybe) doesn't add them to the key chain but the key evidently (by trial and error :D) is not in DER format and therefore I can't load it like this.
SecCertificateRef certificateRef = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)data); //data contains the public key - received over the network
SecPolicyRef policyRef = SecPolicyCreateBasicX509();
SecTrustRef trustRef;
OSStatus status = SecTrustCreateWithCertificates(certificateRef, policyRef, &trustRef);
NSAssert(status == errSecSuccess, #"SecTrustCreateWithCertificates failed.");
SecTrustResultType trustResult;
status = SecTrustEvaluate(trustRef, &trustResult);
NSAssert(status == errSecSuccess, #"SecTrustEvaluate failed.");
SecKeyRef publicKey = SecTrustCopyPublicKey(trustRef); //The Result :)
NSAssert(publicKey != NULL, #"SecTrustCopyPublicKey failed.");
if (certificateRef) CFRelease(certificateRef);
if (policyRef) CFRelease(policyRef);
if (trustRef) CFRelease(trustRef);
PS: Why does apple make this so hard? Statically linking OpenSSL would be easy, but then all sorts of export regulations and other problems apply.
The problem was apparently with the source of the "certificate", which really wasn't much more than the key wrapped in some DER tags.
On the plus side thanks to the black magic in this http://blog.wingsofhermes.org/?p=75 blog post, I have successfully managed to achieve most of my goals.
Success:
Key loaded from data, not a file
Encryption of secret (AES) key successfully read by java server.
Less success:
Had to use a unique identifier, but I reuse it, so no need for a crazy naming scheme.
Key temporarily added to keychain, but I remove it after its one time use, so that works out too.
I am still not too clear on what the array of if statements mixed with loops and tons of magic numbers does exactly, but at least it works and since the key will always come from the same source, it shouldn't break unless they change the java security provider...oh wait thats actually kinda likely...oh well...at least its a little bit specific in the Java 7 standards.
*crosses fingers* *hopes nothing breaks*
We're developing a service that will accept a POST request. Some of the POST data will need to be encrypted before the POST as it will be stored in hidden fields on a form.
The application is written in C#, but we want third party clients to be able to easily integrate with it. We find that most clients use PHP, Classic ASP or VB.Net.
The third parties should only be doing the encryption. We'd do the decryption. There is no two-way communication.
What are the most compatible combinations of encryption algorithm, padding mode and other options?
Assuming that you have a safe way of sharing a key (whether RSA encryption of it, retrieval over an SSH or HTTPS link, or callling the other developer on a secured phone line), any of the major modern encryptions (like AES, as mentioned by #Ed Haber) would be suitable. I would second his suggestion of AES. There should be libraries for PHP, VB, Ruby, etc.
However, remember that with "no two-way communication" you will have to find an out-of-channel method for securely getting the symmetric key to the encrypting party.
If you mean that it should be impossible for third-parties to decrypt data, then you will want to use an asymmetric encryption algorithm such as RSA. This will the third-party to encrypt data with your public key, and then only you can decrypt the data with your private key, which you do not disclose. There should be implementations of RSA available for all the languages you mentioned.
If you don't care if the third-party can decrypt the data, then AES is the way to go. You will have one key which you share with the third-parties. This key is used both for encryption and decryption.
I would use AES for the bulk data encryption and RSA for encrypting the AES Key.
If the data is small enough then just encrypt the whole thing with RSA.
Ed Haber said
I would use AES for the bulk data
encryption and RSA for encrypting the
AES Key. If the data is small enough
then just encrypt the whole thing with
RSA.
I think this is a good solution. What I would do is have your application publish an API for getting a public RSA key. When I third party wants to send you something it gets the public key. It then generates a session key to do the actual encryption using a block cipher, (ie AES), and sends the key to you by encrypting with your public key. You decrypt the session key with your private key. The third party then encrypts the data it wants to send you with AES (using a padding scheme that you also publish) and sends it to you. You decrypt it using the session key.
There are some problems with the method above. Since you are not sending any information (other than publishing your public key, you cannot control how the session key is generated. This means that third parties can use very insecure ways to of generating the session key and you will never know. A second problem is everyone who wants to send you data has to pad data for AES in the same way you do. So you will have to make sure every one co-ordinates. The second issue isn't to big, but the first could be a problem especially if you don't trust the third parties all that much to generate really good session keys from a good cryptographically secure random number generator
You could very easily implement your own XOR key-based bit encryption. With a little thought and ingenuity, you can come up with something that's more than suitable for you application.
Here's a PHP example:
function XOREncryption($InputString, $KeyPhrase){
$KeyPhraseLength = strlen($KeyPhrase);
for ($i = 0; $i < strlen($InputString); $i++){
$rPos = $i % $KeyPhraseLength;
$r = ord($InputString[$i]) ^ ord($KeyPhrase[$rPos]);
$InputString[$i] = chr($r);
}
return $InputString;
}
ColdFusion has the encrypt and decrypt functions capable of handling a range of algorithms and encodings, including the AES recommended above.
Information at: http://www.cfquickdocs.com/cf8/?getDoc=encrypt#Encrypt
Quick example code:
Key = generateSecretKey( 'AES' , 128 )
EncryptedText = encrypt( Text , Key , 'AES' , 'Hex' )
Text = decrypt( EncryptedText , Key, 'AES' , 'Hex' )
Similar functionality is available with this library for PHP:
http://www.chilkatsoft.com/p/php_aes.asp
...and Java, Python, Ruby, and others...
http://www.example-code.com/java/crypt2_aes_matchPhp.asp
http://www.example-code.com/python/aes_stringEncryption.asp
Sounds like RSA is the algorithm for you.
Why not have your server exposed over HTTPS? That way, any client which can handle HTTPS can consume the service securely.