JWT Token Encryption - jwt

I am looking to encrypt my JWT token. I have gone through the quarkus documentation and the various properties for JWT. However i am not able to figure out what is going wrong. The basic stuff with a simple signing bit works fine,
Jwt.claims(jsonObject).sign();
here i have set 2 properties,
mp.jwt.verify.publickey.location=publicKey.pem
smallrye.jwt.sign.key.location=privateKey.pem
For Encryption bit, according to the doc I am setting 2 additional properties,
mp.jwt.decrypt.key.location=privateKey.pem
smallrye.jwt.encrypt.key.location=publicKey.pem
And the code being used is,
Jwt.innerSignAndEncrypt(jsonObject);
When I turn on verification tracing, I am getting the following exception in the logs,
Caused by: org.jose4j.lang.InvalidKeyException: The key must not be null.
at org.jose4j.jwx.KeyValidationSupport.notNull(KeyValidationSupport.java:72)
at org.jose4j.jwx.KeyValidationSupport.castKey(KeyValidationSupport.java:56)
at org.jose4j.jwe.RsaKeyManagementAlgorithm.validateDecryptionKey(RsaKeyManagementAlgorithm.java:57)
at org.jose4j.jwe.JsonWebEncryption.createDecryptingPrimitive(JsonWebEncryption.java:225)
at org.jose4j.jwe.JsonWebEncryption.decrypt(JsonWebEncryption.java:240)
at org.jose4j.jwe.JsonWebEncryption.getPlaintextBytes(JsonWebEncryption.java:85)
at org.jose4j.jwe.JsonWebEncryption.getPlaintextString(JsonWebEncryption.java:78)
at org.jose4j.jwe.JsonWebEncryption.getPayload(JsonWebEncryption.java:93)
at org.jose4j.jwt.consumer.JwtConsumer.process(JwtConsumer.java:366)
Not sure what key needs to be set.
Note: For testing, I am using the same RSA key pair for both signing and encryption.
Any help is greatly appreciated.
TIA

I posted this on Quarkus chat as well. Where while creating a reproducer app for them I used the latest Quarkus version 2.1.3. There I encountered a different exception,
Caused by: org.jose4j.lang.InvalidAlgorithmException: 'RSA-OAEP-256' is not a permitted algorithm.
at org.jose4j.jwa.AlgorithmConstraints.checkConstraint(AlgorithmConstraints.java:80)
On investigating this further, it seemed to be an issue in smallrye where the even though the documented default algorithm is "RSA-OAEP", it's trying to default to "RSA-OAEP-256".
The solution was to set the property(smallrye.jwt.decrypt.algorithm) explicitly to "RSA-OAEP-256", while they add a fix.

Related

JAX-WS Metro, how to intercept correct encrypted/signed message with invalid characters / signature mismatch

My question is quite related to this one
I have spend weeks of headaches to try and fight it, but there doesn't seem to exist a solution worthy of mention, apart from the solution to the above question, which is a terrible workaround, but there really seem to exist nothing else around.
We are trying to communicate with a legacy system that has an established and running web service, with certain WS-Security constraints declared in its WSDL. We cannot change anything on the server, we just have to do as it bids. We also have a third party client implementation that actually works and communicates with the server, so we know that the communication works - using THAT specific client. Now, we want to make our own.
The above WS-Security policy includes encryption and signing. There were following scenarios of what to do:
write our own code to encrypt/decrypt and sign/verify
use one of the ready JAX-WS implementations to do the above for us
The second option of course is what we tried to do. Then we branch into following:
Metro/WSIT
Apache CXF
Everybody on the web suggests the latter option (which I tried too) - but for the time being I went with the first one (especially since we do not have any integration with Spring to take advantage of CXF's good integration with it)
After struggling with a bit of ambiguous documentation and various wizards (NetBeans), we came to a solution that contained very little custom code, a configuration file with some keystores, and the usual generated code from wsimport utility.
Some time passed, it included dumping the XML SOAP requests and responses, comparing the failing ones that we produce to the successful ones from the 3rd-party client. Lots of pain, with no results - the messages were different variously, but the core logic and structure was okay - then - you couldn't actually compare the encrypted parts. After some time I ended up with a client that sent something, and actually received something back, but failed to decrypt the response.
Actually it was decrypted alright, but the signature digest verification was failing. It is worth to mention that the original XML message contained a "&" character, as well as multiple newlines. I.e. the payload of the SOAP message was not syntactically correct XML. Anyway.
It seems that this digest verification is deeply rooted inside Metro/WSIT stack and there was absolutely no way I could find to actually intercept and correct that digest - or actually the contents upon which this digest was calculated - obviously - the problem was that some special characters were translated or canonicalized either after or before the digest calculation, and we (rather the underlying implementation that I tried to use to keep my hands clean) did something different from what the server side of the web service did.
Even the Metro tubes (nice name, but horrendously scarce documentation - it seems that nobody uses Metro/WSIT these days - or, should I say, nobody uses SOAP, or SOAP with this level of security? - when I tried Apache CXF, the generated SOAP messages were deceptively similar) and their way of intercepting messages didn't seem to help - when trying to get the raw contents of the message, no provided methods (Packet.getMessage().writeTo... - and other variations) could actually bypass the digest verification thing - because they ALL tried to read the contents the StAX way, streaming etc. (invoking StreamingPayLoadDigester.accept that invariably failed)
But hope would die last, and I would try again and again to find some obscure undocumented magic to make my thing work. Okay, i was about to call it a day and dig hard into java encryption - until I found the above question, that is. Actually it "exploits" a log message that gets printed from deep within the Metro code (actually from wssx-impl I think) with the canonicalized decrypted message, before throwing the digest mismatch exception. Thankfully, this message gets printed using java.util.logging, and this can be intercepted in various ways - e.g. to send it in some kind of synchronized queue, to be consumed by my client. Ugh. If somebody has a better idea, please write your thoughts.
Thank you all.
Finally I resorted to rebuilding Metro/WSIT version 2.1.1 found on GitHub, commenting a single line in WS-SX Implementation project (ws-sx\wssx-impl...\StreamingPayloadDigester.java:145)
if (!Arrays.equals(originalDigest, calculatedDigest)) {
XMLSignatureException xe = new XMLSignatureException(LogStringsMessages.WSS_1717_ERROR_PAYLOAD_VERIFICATION());
logger.log(Level.WARNING, LogStringsMessages.WSS_1717_ERROR_PAYLOAD_VERIFICATION()); //,xe);
// bypass throwing exception
// throw new WebServiceException(xe);
}
It could have been done in a better way, introducing a flag, for instance.
The order of the projects, starting from the smallest one where I did the change, to the one I include into my own project as Metro implementation is approximately as follows:
WS-SX Implementation is referenced in ->
WS-Security Project is referenced in ->
Metro Web Services Interoperability Technology Implementation Bundle (wsit-impl) is referenced in ->
Metro Web Serrvices Runtime non-OSGi Bundle (webservices-rt) included in my client

Can access to play secret allow server compromise/cryptocurrency theft?

Our play secret was leaked in source version control system. Few days later our server was compromised and cryptocurrency stolen. Could it be correlated?
What exactly can be done using play secret?
Suppose attacker does not have latest source but an older version and our servers secret, can he do much?
What exactly?
In regards to what one can do with a play secret. The answer is in the documentation
Anyone that can get access to the secret will be able to generate any session they please, effectively allowing them to log in to your system as any user they please. Hence it is strongly recommended that you do not check your application secret into source control. Rather, it should be configured on your production server. This means that it is considered bad practice to put the production application secret in application.conf.
Given that one can get a session and possibly log into your system that way, I would say that it's probably likely that your secret being stolen and then something in your system being stolen a bit afterward is related. That said, the only way you can tell is by auditing your system's logs to try to figure stuff out. Which I don't think anyone but you can do. Best of luck!
It's possible your data has been altered because one can possibly logon to your system because he can generate sessions with access to your play secret (Refer to answer above) you can try checking your logs(which only noob will keep logs.
Try reading this for more insights just in case of next time, be careful

client-server game secure architecture

I am currently designing a distributed iOs game. It must contains kind of an authentication (username, password pair I think but please give me other idea if you have). I plan to do it through a simple RESTful API coded in Perl.
I know it is kind of a classic problems. I've seen lots of posts on the web talking about how to do this securely. However, too much informations kill its informative goal. So, I am a bit lost. Nevertheless, I've tried to outpoint the basics concepts, namely:
use SSL (so use https url), it allows you not to think about encryption
use embedded private keys shared between the server and the client, but how to embed them is the question! It allows to use HMAC and to do kind of an authentication.
forget about absolute security (because you use security by obscurity): if anyone can destroy your security by decompiling your app, you gonna have problems !
Here are the questions:
how to share private keys ?
what to send to the server ? username/password encrypted ? some api key ?
do I have the right approach (securing a personal restful api) ?
Thanks !
First of all, it's quite broad question. So it may get closed because of this.
Trying to break down your questions to sub-questions/sub-notes
1) First and most important, as you pointed out. There is no absolute security. You should defined what is valuable (what are you trying to protect) and against who are you trying to protect:
unauthorized user
unauthorized user with inner knowledge of your app (reverse engineered)
authorized user with inner knowledge of your app (reverse engineered)
1) https is "the must". As you figured it out, you don't have to worry about privacy and integrity.
2) In most cases, an app should send username and plain password. This password should be hashed by the server (don't forget to add some salt to it) and compare to stored hashes in your DB.
3) I don't think that you need to share any private keys between client and servers for several reasons:
SSL ensures privacy (so no one can eavesdrop)
Encryption of any parameters using shared secret key which is hardcoded doesn't help too much (it could be reverse engineered and extracted from your app)

REST(ful) simple authentication without SSL and HMAC?

I wonder if it is possible to have an easy authentication method that is restful, fast and provides a litte security.
SSL is not an option, because I can't rely on a valid SSL Certificate on the server of clients. Also HMAC is not really possible because the body of the request should be signed, when used properly, but in my case that body could be a large file. Further should the authentication be possible with JavaScript/AJAX.
I thought about something really simple. What's the problem with that one:
HEADER: X-Authentication: timestamp:username:sha256(timestamp:password)
The server knows the users password and could check the hash, the timestamp is used to only allow request that took place e.g. 10 seconds before. The replay window would be extremly small, and there are no sessions on the serverside.
If the hash is cracked the attacker knows the password and has unlimited access.
Alternative would be to use
HEADER: X-Authentication: timestamp:username:HMAC(password, 'timestamp+request-method+verb')
What's the way to go? I'm not a security pro, maybe storing the session on the server would be better (but not RESTful)?
I built a random hash algorithm that does what you need, it's called jAuthenticate.
You can download it from: https://github.com/thomasoeser/jAuthenticate​
You can see how it works here: http://furiousgryphon.com/jauthenticatedemo.html
The reason it's a strong algorithm (in my opinion) is that I'm using a random number to influence the hash but I'm sending an obfuscated number with the hash.
Each hash is single use only.
Have a look, it's free open source (MIT).
HTTP authentication is extensible so you can invent your own mechanism (obviously at your own risk!). See https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-p7-auth-20 for details.
Don't bother inventing your own new X- header. Using the existing Authorization header with your scheme is a better option.
e.g.
Authorization: kruemel-auth timestamp:HMAC(password, 'timestamp+request-method+verb')
Ideally new schemes will be registered with IANA along with a specification. A registry is being setup to track auth schemes that have been developed. See http://tools.ietf.org/id/draft-ietf-httpbis-authscheme-registrations-03.html

X509: What's the difference between digital signature and non-repudiation

I have to deal with certificates issued by the Swiss post office on USB tokens. There deliver two certificates on the same token. In their intended usage fields, one has "non repudiation" and the other "digital signature".
Now, I can't understand what the practical difference between the two are: I've always seen both in the same certificate, never two certs for the same identity each with one of the roles. In fact, I can't imagine a scenario where non-repudiation and digital signature aren't the same, for all practical matter, the same thing.
Could anyone explain to me what the difference is, please ? And if you had a suggestion about in what situation one should be picked over the other, that would help as well.s
I realise this question is a bit old, but I think I can shed some much-needed light on the question.
The non-repudiation value in the keyUsage attribute relates to the whole certificate, not any purpose in particular. The presence of the non-repudiation flag indicates that the private key has sufficient protections in place that the entity named in the certificate cannot later repudiate—deny—actions they take with the certificate. The presence of the flag doesn't prevent repudiation, rather it indicates that repudiation isn't likely to survive reasonable scrutiny.
So in this specific case, the CA is giving the user the option of a certificate that does or does not include the non-repudiation element. If you want to assert to those verifying the signature that you can't easily deny it was you who signed it (the USB token is the key enabler here), use the non-repudiation certificate. Otherwise, use the certificate marked for digital signatures. (Depending on the other attributes in the certificate, you may or may not be able to sign documents with either or both certificates.)
See Wikipedia: http://en.wikipedia.org/wiki/Non-repudiation
See also the relevant RFC: http://www.faqs.org/rfcs/rfc3280.html (section 4.2.1.3)
I talked to the guy who implemented it and, apparently, they intended the "non-repudiation" cert for /really/ signing documents and the "digital signature" one to be used for authentication.
"digital signature" means that you can guarantee the origin of the document or the id of the user; this is AUTHENTICATION.
"non repudiation" means that the document is approved, this is content commitment also called ELECTRONIC SIGNATURE (not digital signature).
Hope this helps because one's always asked this question even in 2013.
Interesting question, and your thoughts match my own.
I've found a reference at IBM here about key usage, but I still can't really get my head around the distinction.
The best that I can phrase my understanding having read the article is that a non-repudiation usage means "I really meant to sign this, and I really understand the implications of signing this."
Sorry this isn't a complete answer, but I hope it helps.
EDIT 4th April 2014
I just got given more points again. The answer from #Calrion is much better, so send any +1s that way.
"digital signature" should be used for authentication (it was you, who signed this), while "non repudiation" means that you know what you was signed.
If you use your private certificate for authentication (against some server) the authentication works following way: During establishing the connection your browser (or other SW) signed some random data provided by server to prove that it was you on the other side. But the key point is that you have no control which data you are signing. Thus the server can you send instead of random data send "I, Petr Novonty, give all my money to James Clark."
To avoid this, key used for signing some documents should have "non repudiation" and not "digital signature" bits set.
This page gives somewhat clear descriptions of all the key usages:
https://www.ibm.com/support/knowledgecenter/en/SSKTMJ_9.0.1/admin/conf_keyusageextensionsandextendedkeyusage_r.html.
Keep in mind, that X.509 renamed the nonRepudiation bit in contentCommitment. This seems to be better than a description via "non". So this remark supports the answer given by Franck Leroy.
Note that they are simple bits, their names give only indications for the key usage. Some explanations of these bits are given in RFC 5280. But how to interpret distinctions between these two is finally left to the certificate issuer. RFC 5280 says on this "Further distinctions between the digitalSignature and nonRepudiation bits may be provided in specific certificate policies."
https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.3