I have configured Vault Transit secrets engine with encryption key of type RSA-2048.
After signing some input data I have got a some signature and would like to verify it locally using public key and not interacting with Vault server.
Secrets engine: Transit
Encryption key type: RSA-2048 (public and private keys are available)
Sign parameters:
Hash algorithm: sha2-256
Signature algorithm: pss
Vault sign input: Base64(“aaa”) = “YWFh”
Vault sign output: vault:v1:fjgCO0r…==
In order to verify generated signature (for investigation purposes) I use web site https://8gwifi.org/RSAFunctionality?rsasignverifyfunctions=rsasignverifyfunctions&keysize=2048 that allows verify signature.
I provide there:
public key
input text
generated signature( without prefix “vault:v1:”)
and choose RSA Signature Algorithms = SHA256withRSA.
I have got an error Signature Verification Failed.
Could you explain what the structure of Vault generated signature and how it could be verified offline?
Related
I have a token issued by Azure AD. I need to verify the token in my API, which is running on IBM platform.
I am writing the token verifier in Java,using
claims = Jwts.parser().setSigningKeyResolver(signingKeyResolver).parseClaimsJws(accessToken);
The signingKeyResolver is returning a public key. No issues.
I use the following code to get the public key :
BigInteger modulus = new BigInteger(1, Base64.getUrlDecoder().decode(key.getN()));
BigInteger exponent = new BigInteger(1, Base64.getUrlDecoder().decode(key.getE()));
RSAPublicKeySpec publicSpec = new RSAPublicKeySpec(modulus, exponent);
KeyFactory factory = KeyFactory.getInstance("RSA");
Provider provider = factory.getProvider();
PublicKey pubkey = factory.generatePublic(publicSpec);
return factory.generatePublic(publicSpec);
Can any one throw some light on Why the signature is invalid ? I observe one thing when I create the factory, the Provider name shows IBMJCEPLUS. Does it have any impact on the key generation ? If so, how do I create the correct factory for Microsoft issued keys ?
Looking for a general advice in creating the factory..
Several things.
the sample is incomplete, and seems mixed up. Is this the role of consumer doing a signature verification?
You are generating a public key which is not an expected behaviour for the verify method of a consumer, you typically 'use' the JWK retrieved from the JWKS URL provided by the JWT producer (AzureAD) not generate a new public key that was not used to generate the signature? To verify a signature, you need to reproduce the same signature by having all the inputs the server used when they generated it. A signature is simply a representation of the payload to ensure the payload was not modified, i.e. integrity check. This is the purpose of the signature and why you must have the same inputs to generate it on the client, wither you gain the inputs used out-of-band somehow (not how AzureAD works) or you use the JWKS to retrieve the appropriate public key for the verify method.
It appears you also expect there to be encrypted claims, based on the RSA reference in your example. If this is intended you would also require you to decipher the payload to access the cleartext. This requires you to have implemented the appropriate PKI. As a consumer (client) the private key must be generated and never shared (or retrieved). Encryption implemented correctly ensures that only the client intended to read the cleartext data 'can' decipher it with the private key, which it itself generated for this purpose, and only it (the client) has control of the private key. Have you the appropriate PKI to do the encrypted JWT properly? Or are you expecting to only utilise the HMAC-based JWT that has no encryption at all and relies on only signature verification (and therefore all claims are public, not protected).
To summaries, there are 2 distinct modes of JWT; 1) HMAC-based that uses signatures where the same inputs are needed on client to verify the signature as was used on server to generate the signature, and this is for integrity only, there is no encryption to protect data. 2) encryption-based JWT that uses a public key for signature verification and the private key used by clients to decipher the encrypted claims data.
1 requires PKI, 2 doesn't.
2 has no data protection and is useful for stateless claims that are intended to be public and therefore verification of the 'claims' before use is how you gain security assurance. Whereas 1 offers the security characteristic of confidentiality and if the PKI is done correctly (private keys are never shared) then the confidential claims data can have more private use cases.
I'm trying to understand the logic of using JSON web tokens with private/public keys (RS512) when signing a payload of data sent from a client (in this case, a React Native App) to my server.
I thought the whole point of private/public keys was to keep the private key private (on my server) and hand the public key to the person who's successfully logged into the app.
I thought, with each API request to my server, the authenticated user of the app would use the public key to create the JWT (on the client side) and the server would use the private key to verify the signature/payload from the API request.
It seems I have it backwards because everywhere I read, you're supposed to sign a JWT with the private key -- but that goes against my understanding of who's in possession of the keys.
Depending on how the keys are created, some private keys can have a passcode which is supposed to be secret! So if the private key and the secret is out in the open (in client-side code) how secure can that be?
And where does the encryption come in? If the user of the app is sending sensitive data in the API, am I supposed to encrypt the payload and sign it with the JWT on the client side and then let the server verify the JWT signature and decrypt the data?
This tutorial was helpful https://medium.com/#siddharthac6/json-web-token-jwt-the-right-way-of-implementing-with-node-js-65b8915d550e but it seems backwards.
Any explanation would definitely help because all of the on-line tutorials aren't making sense.
Thank you.
With JWT, the possession and the use of the key materials are exactly the same as any other contexts where cypher operations occur.
For signing:
The private key is owned by the issuer and is used to compute the signature.
The public key can be shared with all parties that need to verify the signature.
For encryption:
The private key is owned by the recipient and is used to decrypt the data.
The public key can be shared to any party that want to send sensitive data to the recipient.
The encryption is rarely used with JWT. Most of the time the HTTPS layer is sufficient and the token itself only contain a few information that are not sensitive (datatime, IDs...).
The issuer of the token (the authentication server) has a private key to generate signed tokens (JWS). These tokens are sent to the clients (an API server, a web/native application...).
The clients can verify the token with the public key. The key is usually fetched using a public URI.
If you have sensitive data that shall not be disclosed to a third party (phone numbers, personnal address...), then the encrypted tokens (JWE) is highly recommended.
In this case, each client (i.e. recipient of a token) shall have a private key and the issuer of the token must encrypt the token using the public key of each recipient. This means that the issuer of the token can select the appropriate key for a given client.
Hope this figure adds some clarity.
Solution for JWE in React Native and Node Backend
The hardest part was finding a method that works in both RN and Node because I can't just use any Node library in RN.
I'm transmitting all of the API calls over HTTPS.
Create a JWE to encrypt the token and payload simultaneously.
React Native App Code
import {JWK, JWE} from 'react-native-jose';
/**
* Create JWE encrypted web token
*
* #param payload
* #returns {Promise<string>}
*/
async function createJWEToken(payload = {}) {
// This is the Public Key created at login. It is stored in the App.
// I'm hard-coding the key here just for convenience but normally it
// would be kept in a Keychain, a flat file on the mobile device, or
// in React state to refer to before making the API call.
const publicKey = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApl9FLYsLnP10T98mT70e
qdAeHA8qDU5rmY8YFFlcOcy2q1dijpgfop8WyHu1ULufJJXm0PV20/J9BD2HqTAK
DZ+/qTv4glDJjyIlo/PIhehQJqSrdIim4fjuwkax9FOCuFQ9nesv32hZ6rbFjETe
QSxUPjNzsYGOuULWSR3cI8FuV9InlSZQ7q6dEunLPRf/rZujxiAxGzY8zrMehjM5
LNdl7qDEOsc109Yy3HBbOwUdJyyTg/GRPwklLogw9kkldz5+wMvwOT38IlkO2rCr
qJpqqt1KmxdOQNbeGwNzZiGiuYIdiQWjilq5a5K9e75z+Uivx+G3LfTxSAnebPlE
LwIDAQAB
-----END PUBLIC KEY-----`;
try {
const makeKey = pem => JWK.asKey(pem, 'pem');
const key = await makeKey(publicKey);
// This returns the encrypted JWE string
return await JWE.createEncrypt({
zip: true,
format: 'compact',
}, key).update(JSON.stringify(payload)).final();
} catch (err) {
throw new Error(err.message);
}
}
Node Backend
const keygen = require('generate-rsa-keypair');
const {JWK, JWE} = require('node-jose');
/**
* Create private/public keys for JWE encrypt/decrypt
*
* #returns {Promise<object>}
*
*/
async function createKeys() {
// When user logs in, create a standard RSA key-pair.
// The public key is returned to the user when he logs in.
// The private key stays on the server to decrypt the message with each API call.
// Keys are destroyed when the user logs out.
const keys = keygen();
const publicKey = keys.public;
const privateKey = keys.private;
return {
publicKey,
privateKey
};
}
/**
* Decrypt JWE Web Token
*
* #param input
* #returns {Promise<object>}
*/
async function decryptJWEToken(input) {
// This is the Private Key kept on the server. This was
// the key created along with the Public Key after login.
// The public key was sent to the App and the Private Key
// stays on the server.
// I'm hard-coding the key here just for convenience but
// normally it would be held in a database to
// refer during the API call.
const privateKey = `-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEApl9FLYsLnP10T98mT70eqdAeHA8qDU5rmY8YFFlcOcy2q1di
jpgfop8WyHu1ULufJJXm0PV20/J9BD2HqTAKDZ+/qTv4glDJjyIlo/PIhehQJqSr
dIim4fjuwkax9FOCuFQ9nesv32hZ6rbFjETeQSxUPjNzsYGOuULWSR3cI8FuV9In
lSZQ7q6dEunLPRf/rZujxiAxGzY8zrMehjM5LNdl7qDEOsc109Yy3HBbOwUdJyyT
g/GRPwklLogw9kkldz5+wMvwOT38IlkO2rCrqJpqqt1KmxdOQNbeGwNzZiGiuYId
iQWjilq5a5K9e75z+Uivx+G3LfTxSAnebPlELwIDAQABAoIBAQCmJ2FkMYhAmhOO
LRMK8ZntB876QN7DeT0WmAT5VaE4jE0mY1gnhp+Zfn53bKzQ2v/9vsNMjsjEtVjL
YlPY0QRJRPBZqG3wX5RcoUKsMaxip3dckHo3IL5h0YVJeucAVmKnimIbE6W03Xdn
ZG94PdMljYr4r9PsQ7JxLOHrFaoj/c7Dc7rd6M5cNtmcozqZsz6zVtqO1PGaNa4p
5mAj9UHtumIb49e3tHxr//JUwZv2Gqik0RKkjkrnUmFpHX4N+f81RLDnKsY4+wyI
bM5Gwq/2t8suZbwfHNFufytaRnRFjk+P6crPIpcfe05Xc+Y+Wq4yL62VY3wSS13C
EeUZ2FXpAoGBANPtw8De96TXsxdHcbmameWv4uepHUrYKq+7H+pJEGIfJf/1wsJ0
Gc6w2AE69WJVvCtTzP9XZmfiIze2sMR/ynhbUl9wOzakFpEh0+AmJUG+lUHOy4k2
Mdmu6GmeIM9azz6EXyfXuSZ39LHowS0Es1xaWRuu5kta73B5efz/hz2tAoGBAMj4
QR87z14tF6dPG+/OVM/hh9H5laKMaKCbesoXjvcRVkvi7sW8MbfxVlaRCpLbsSOs
cvAkc4oPY+iQt8fJWSJ1nwGJ0g7iuObLJh9w6P5C3udCGLcvqNbmQ9r+edy1IDBr
t7pdrFKiPFvaEEqYl06gVSsPCg041N6bRTJ1nEzLAoGAajSOVDqo6lA6bOEd6gDD
PSr+0E+c4WQhSD3Dibqh3jpz5aj4uFBMmptfNIaicGw8x43QfuoC5O6b7ZC9V0wf
YF+LkU6CLijfMk48iuky5Jao3/jNYW7qXofb6woWsTN2BoN52FKwc8nLs9jL7k6b
wB166Hem636f3cLS0moQEWUCgYABWjJN/IALuS/0j0K33WKSt4jLb+uC2YEGu6Ua
4Qe0P+idwBwtNnP7MeOL15QDovjRLaLkXMpuPmZEtVyXOpKf+bylLQE92ma2Ht3V
zlOzCk4nrjkuWmK/d3MzcQzu4EUkLkVhOqojMDZJw/DiH569B7UrAgHmTuCX0uGn
UkVH+wKBgQCJ+z527LXiV1l9C0wQ6q8lrq7iVE1dqeCY1sOFLmg/NlYooO1t5oYM
bNDYOkFMzHTOeTUwbuEbCO5CEAj4psfcorTQijMVy3gSDJUuf+gKMzVubzzmfQkV
syUSjC+swH6T0SiEFYlU1FTqTGKsOM68huorD/HEX64Bt9mMBFiVyA==
-----END RSA PRIVATE KEY-----`;
try {
const makeKey = pem => JWK.asKey(pem, 'pem');
const key = await makeKey(privateKey);
// This returns the decrypted data
return await JWE.createDecrypt(key).decrypt(input);
} catch (err) {
throw new Error(err.message);
}
}
jwt.io does a great job of explaining that there is more than one way to sign the JWT. Users may sign and verify with a single secret, or use a public/private key pair for verifying/signing respectively.
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.
Although JWTs can be encrypted to also provide secrecy between
parties, we will focus on signed tokens. Signed tokens can verify the
integrity of the claims contained within it, while encrypted tokens
hide those claims from other parties. When tokens are signed using
public/private key pairs, the signature also certifies that only the
party holding the private key is the one that signed it.
I am generating JWT using Node.js with require('jsonwebtoken') using public key which is generated by puttygen tool in windows. Then i will pass that token to other application in headers. The Other application is not developed in Node.js. Using java I need to validate the token with public key. But none of the sites i found a valid sample to verify using public/private key.
Can any one please provide me steps how i can load public/private key in java and verify jwt token. Please provide me examples if any you have. Thanks in advance.
Sample public key (public.pem) :-
---- BEGIN SSH2 PUBLIC KEY ----
Comment: "rsa-key-20160721"
AAAAB3NzaC1yc2EAAAABJQAAAQEAhk1i7Jwz2M6zakReDgg0NkVPn1kK1R8qAp2p
Ayh0eUPCb2XICDDVRnpUIK7/4k4dlLeeSi10TwwXe85zZ0gXcNMIOpnEKIWcnqJM
ctbYwyrl2tAb/tKjvBCvHMA9ZnfNADkN6reBZq8u7kYJ3bF9PxvS3QM+vgJ8/8ZS
qkRWcsmRZdq+wthwGt43J3NSKFfhMVP08/V/hTASq06vvFYApHsEH6zLxNNQ63Tt
Bzedh+C5efyqYqEVqnA7S9bXimyY2ViqpqFTx1lM9dV+12dSOxd7CQzX8eo00Phi
EAnY2hfoTooUeCO3/L6YavRl+CXgjhvA9mg4QO554qI1YCUvBw==
---- END SSH2 PUBLIC KEY ----
Node JS code:-
var privateKey = fs.readFileSync("public.pem");
var userData = {username:'John'};
var token = jwt.sign(userData, privateKey);
Java Code:-
Needed java code which can verify above token using above public key.
Cryptographic operations are independent of programming language. You can perfectly generate a JWT in nodeJS and verify in Java.
JWT is digitally signed with the private key and signature is verified with public key. In case of HMAC symmetric keys, the key to sign and verify is the same.
Use a JWT library for Java like https://github.com/jwtk/jjwt
Jwts.parser().setSigningKey(key).parseClaimsJws(compactJws);
In the page you can see the supported algorithms.
Putty uses its own key format. Java does not supports it. You need to export the Putty SSH2 key to the OpenSSH format. See
How can I read RSA keys in Java?
I'm working on project which is required SSO implementation between WebShpere and PHP web application.
However after i take a look at possible ways to implement SSO i find the LTPA token which is used to implement SSO between different IBM technologies.
but LTPA token 2 is encrypted cookie file. which i should decrypt if i want to use information inside this file such as (userid, username, email ... etc).
i have make deep search about LTPA token 2 and below is the best definition i find from IBM.
LTPA2 signatures are generated using SHA-1 as the hash algorithm, and
RSA (1024-bit key) as the encryption algorithm. After the digital
signature has been attached, the user data and signature are encrypted
with a 3DES or AES key obtained from the LTPA key file (refer to
“Consuming LTPA tokens” and “Generating LTPA tokens”).
But i'm still trying to decrypt this token with no luck.
Any help ?
The Alfresco project did this. Take a look at this blog post for pointers, including working code.
To clarify things, the contents of LTPA tokens are strings that are more or less like "uid=user,cn=users,ou=myorg,dc=com#ldaprealm%timeout%[RSA signature]", encrypted with the shared AES key and encoded with Base64. LTPA v2 will not use 3DES, but only AES. So what you need really to do is to AES decrypt the cookie, and you can already read the username. You don't have to verify the RSA signature.
Why do you need to decrypt it from file? Isn't the token passed along with the calls that you made? When passed, LTPA token is encoded via Base64 and you can easily decode it. Below is an example of how to obtain information from token:
import javax.security.auth.Subject;
import javax.xml.bind.DatatypeConverter;
import com.ibm.websphere.security.cred.WSCredential;
import com.ibm.wsspi.security.token.Token;
Subject subject = ...; // obtain current JAAS subject
Set<?> publicCredentials = subject.getPublicCredentials();
for (Object credential : publicCredentials) {
if (credential instanceof Token) {
System.out.println(DatatypeConverter.printBase64Binary(((Token) credential).getBytes()));
System.out.println(((Token) credential).getName());
System.out.println(((Token) credential).getUniqueID());
System.out.println(((Token) credential).getAttributeNames());
}
}
I'm trying validate an X.509 certificate received over a network. I have understood that the digital signature is created by creating a message digest of the fields(don't know which fields) in the signature and then encrypting it using the CA(Certificate Authority) private Key.We can validate the certificate by decrypting the digital signature using CA public key and comparing it with the message digest of the certificate fields.
I'm stuck at this point as I don't know which all fields I should take to create the message digest for the validation. Can somebody please help me out
From a glance at the RFC it appears to be the whole tbsCertificate field.
[...] a digital signature computed upon
the ASN.1 DER encoded tbsCertificate. The ASN.1 DER encoded
tbsCertificate is used as the input to the signature function.