JWT encryption is normal? - web

I'm starting with the JWT, and I did a decryption test of my token on base64 and I actually decrypt it, except for the Signature part that I don't decipher it, my question is: is the JWT token normal to decrypt it? and if it's normal how I can prevent this.
I'am using algorithm HS256
thanksgiving

What you have is not an encrypted token (JWE => RFC7516) but a signed token (JWS => RFC7515).
The algorithm HS256 is a signature algorithm referenced in the RFC7518 section 3.2.
With signed tokens, the payload is not encrypted but only encoded using the Base 64 Url Safe data encoding (see RFC4648).

Related

Have to decrpt a SHA1 password to Forgerock OpenIDM

I have a requirement to decrypt the SHA1 user password from Active Directory to Forgerock OpenIDM, using below java script I am able to decrypt the password in base64.
if (source != null)
{
var base64 = Packages.org.forgerock.util.encode.Base64url
b64tO = new Packages.java.lang.String(base64.decode(source));
logger.info("Decoded: {}", b64tO);
target = b64tO;
}
Could you please help me
I am expecting to decrypt the password from SHA1 to plain text and store it in Forgerock OpenIDM.
Decrypting SHA1 is not possible because it is not an encryption, but a hashing algorithm.
But there are ways so sync a DS password to IDM in cleartext during it being changed. You can use the plugin documented here for that: https://backstage.forgerock.com/docs/idm/7/pwd-plugin-guide/chap-sync-dj.html

OpenPGP.js says elgamal keys are considered too weak

We are using PGP encryption to encrypt files before transfer. We are using the npm package OpenPGP.js to encrypt the files using a public key from the recipient. I have exported the public key in armored format to use with openpgp.encrypt function.
Here is the code to encrypt the file:
const publicKey = await openpgp.readKey({ armoredKey: key.publicKey });
const encrypted = await openpgp.encrypt({
message: await openpgp.createMessage({ text: readStream }),
encryptionKeys: publicKey
});
However the function call produces this error:
Error: Error encrypting message: Could not find valid encryption key
packet in key ea8be7d9f2fd53a7: elgamal keys are considered too weak.
The output of gpg --list-keys gives the following information
pub dsa1024 2010-07-23 [SCA]
ABCDEFGHIJK
uid [ unknown] my recipient <my.recipient#email.com>
sub elg2048 2010-07-23 [E]
I'm able to encrypt a file using GnuPG, but OpenPGP does not seem to like the public key. Is this error message valid? Do I need to request another key from the client, or is there a way to bypass this error message?
*Edit: After some research I have found that DSA-1024/(ElGamal-anything) is not safe anymore, so I'll probably have to request new keys be made.
OpenPGP implementations have different security considerations, and OpenPGP.js seems decided to reject DSA/ElGamal by default via this PR: https://github.com/openpgpjs/openpgpjs/pull/1264/files#
However it is possible to override this behaviour via config, examples are available in tests.

How can I create a signed JWT using npm Jose and then verify this token?

I am struggling to understand how to use the npm jose module (https://www.npmjs.com/package/jose) to create and verify signed JWT tokens in my Node application. My scenario is this: I want to sign an authenticated request to access a resource. I can successfully create a JWT claim for this request grant token that respects the properties of “its” and “aud”, “exp”, etc. but I want to sign it (to wit, using the SignJWT object and the ‘sign’ method) so that when it gets passed back to my server as a request I can validate it and grant or reject access.
The “sign” method doesn’t seem to like anything I pass it for the ‘key’ parameter (I am not passing any options — maybe I should be, but what?).
I am attempting to use RSA key pairs. I want to sign with the private key and verify with the public key. For my immediate need, I suppose I could use a symmetric key instead, but I am thinking of some other future scenarios where I will want this classic PKCS relationship of certificate keys. And at any rate, I don’t think this choice has anything to do with the current roadblock to my progress.
I first tried to use jose/util/generate_key_pair to create my public/private pair. But when I went to use the key, the error informed me this was not supported by my implementation. So I switched to trying to create a ‘pem’ cert outside of my app and applying that (as text), but that also failed. The ‘sign’ method reports that the key must be a ‘KeyLike’, ‘CryptoKey’, or ‘Uint8Array’ type. Well, the UInt8Array (node buffer) is not enough type information: it doesn’t speak to what is in that buffer, and “KeyLike” is such a vague definition that it’s ignorable. After beseeching the oracles of the search engines, I found I could create a key pair in CryptoKey format using the following from Node APIs:
crypto.webcrypto.subtle.generateKey(
{
name: 'RSASSA-PKCS1-v1_5',
modulusLength: 2048,
publicExponent: new Uint8Array([1, 0, 1]),
hash: "SHA-256"
},
true,
[‘sign’, ‘verify’]
).then((pair:any) => {
serverInstance.keyPair = pair
})
But, still, when I get to the signing part:
siaToken.sign(serverInstance.keyPair.privateKey).then(signature => {
I get an exception that reports
“TypeError: CryptoKey does not support this operation”
Thinking this might have to do with the ‘usages’ parameter of generateKey, I tried various values there, but with no success.
So, I am flummoxed. Can anyone tell me how to (a) best produce a pair of keys for this purpose and (b) how to apply these for JWT signing?
I have also struggled with signing and verifying JWT using jose but was finally able to succeed with HS256 symmetric key encryption. I produced it by following steps (I am using jose-node-cjs-runtime for Node.js only use case. Feel free to replace with desired package. Also please note that I have found that these codes are working for Node.js version 16.7.0, 16.9.0 so please ensure that any of them is installed. If you want to deploy these changes to production environment, then also you have to ensure the deploy environment has the same Node.js version. One way this can be achieved is by mentioning Node.js version in engines key in package.json):
Add Required imports
// library for generating symmetric key for jwt
const { createSecretKey } = require('crypto');
// library for signing jwt
const { SignJWT } = require('jose-node-cjs-runtime/jwt/sign');
// library for verifying jwt
const { jwtVerify } = require('jose-node-cjs-runtime/jwt/verify');
Create Secret key of type KeyObject
KeyObject is recommended by Node.js for using when generating symmetric, asymmetric keys. Use following code to generate and store symmetric key object of type KeyObject in secretKey.
const secretKey = createSecretKey(process.env.JWT_SECRET, 'utf-8');
Replace process.env.JWT_SECRET with a sufficiently long string. It needs to be sufficiently long (use strings of length at least 32) otherwise there will be following error thrown when signing the JWT: HS256 requires symmetric keys to be 256 bits or larger
Sign the JWT
(async () => {
const token = await new SignJWT({ id: '12345' }) // details to encode in the token
.setProtectedHeader({ alg: 'HS256' }) // algorithm
.setIssuedAt()
.setIssuer(process.env.JWT_ISSUER) // issuer
.setAudience(process.env.JWT_AUDIENCE) // audience
.setExpirationTime(process.env.JWT_EXPIRATION_TIME) // token expiration time, e.g., "1 day"
.sign(secretKey); // secretKey generated from previous step
console.log(token); // log token to console
})();
Verify the JWT
We will use the same symmetric key stored in secretKey for verification purpose as well. Following code can be used to extract token from request header (in an Express app) and validate the token:
(async () => {
// extract token from request
const token = req.header('Authorization').replace('Bearer ', '');
try {
// verify token
const { payload, protectedHeader } = await jwtVerify(token, secretKey, {
issuer: process.env.JWT_ISSUER, // issuer
audience: process.env.JWT_AUDIENCE, // audience
});
// log values to console
console.log(payload);
console.log(protectedHeader);
} catch (e) {
// token verification failed
console.log("Token is invalid");
}
})();
By far the easiest way to generate the key material is to use generateKeyPair. The method is runtime agnostic and only requires a single argument - the Algorithm Identifier you wish to use the target key pair with. If you're bringing your own keys tho you must be aware of the different requirements for the key in order to be usable by the algorithm.
Not every runtime's crypto capabilities can support every algorithm, the list of available algorithms per runtime is available here.
Furthermore - importing SPKI/PKCS8 encoded key material is platform-specific and done through platform-specific APIs. The ways one can end up with KeyLike (type alias for CryptoKey (web), KeyObject (node), or Uint8Array (symmetric secrets) is documented in, well, KeyLike alias documentation linked from every function doc that uses it.
If you were to provide any actual reproduction code for your steps I would be happy to help.
The ‘sign’ method reports that the key must be a ‘KeyLike’, ‘CryptoKey’, or ‘Uint8Array’ type.
I'm fairly sure it says KeyObject at runtime, KeyLike is merely a type alias covering all the different types of inputs applicable for the different algorithms and runtimes.

GDAX signature example

I just can’t seem to get the signature right and I think some sample data would help me diagnose the problem. Can anyone offer some sample data to help me “calibrate” and make sure my code is functioning properly?
prehash string
base64-encoded secret
base64-decoded secret
sha256 HMAC using the base64-decoded secret key on the prehash string
base64-encoded result
I am working in VBA. Any additional tips/advice would be appreciated.
The answer is no one will provide you with the sample data you are requesting as that would mean they in a sense would be sharing their own private passphrase, API key and secret with you.
go to gdax.com and click on API.
Generate copy the generated passphrase (do not lose this)
Go thru remaining steps to generate API key and secret (do not lose this)
Use the API reference to create authentication requests (signing, HMAC, Etc.)
Consider an easier way to interact with REST API than VBA.
Sample data for "calibration" of your software can use the following inputs:
timestamp: 1517266319.000
method: GET
requestpath: /accounts
secret: D1/0wNj3wsKg8XcTs4KCfZUVzsHXIOW7w38Moj+YximHA5VQS7zAG47bgNSNGIGtFtYQ0vei2JiSPvX3JkBsA==
The correct signature for the above inputs is:
jQxycBtZQKEWUZjtIaFnD1zoUDQebGeHmoIW3KHvmtg=
This is confirmed by both the NodeJS and Python code samples.

Basic Authentication + SSL - what do do with the credentials once they're on the server?

Say a user submits their credentials using basic authentication. I have a custom message handler that retrieves the credentials from the header:
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
System.Threading.CancellationToken
cancellationToken)
{
try
{
// Request Processing
var headers = request.Headers;
if (headers.Authorization != null && SCHEME.Equals(headers.Authorization.Scheme))
{
Encoding encoding = Encoding.GetEncoding("iso-8859-1");
string credentials = encoding.GetString(Convert.FromBase64String(headers.Authorization.Parameter));
string[] parts = credentials.Split(':');
string userId = parts[0].Trim();
string password = parts[1].Trim();
// TODO: Authentication of userId and Pasword against credentials store here
I'm wondering - when I actually authenticate the userId and password here, I'm tempted to compare the plaintext from this method to plaintext stored in the database, but I know this is insecure. Should I be hashing both the plaintext from the header and credentials stored in the database to compare indirectly?
If so, it seems like the credentials are in plaintext in the messagehandler, before they get hashed. Does this present any kind of security vulnerability, or is it ok?
There is data in motion and data at rest. Hashing is typically for data at rest, specifically password kind of things, where the user will be submitting the un-hashed form for you to hash and compare against the authority. If you are worried about clear password stored, hash it and store. Retrieve the password in clear text from the header, hash it and compare against the one in the database. If your concern is sending password over the wire, you should not be using basic authn.
SSL covers you on having the credentials in plaintext as they are passed over the wire.
Passwords should definitely be hashed and salted in the database, and never saved anywhere in plaintext.
Having the passwords in a string variable on the server is really only a problem if you have someone memory-scraping your server. And if that happens, you have bigger problems. If you're concerned about minimizing that window of availability, you can take the password from the header and put it into a byte array instead of a string, so you can clear the byte array as soon as you are finished with it. However, the value is already stored in a string in headers.Authorization.Parameter, so that may not gain you much.

Resources