Timestamp request with file hash already generated in client - java

I need to make a timpestamp request to a tsa of a large data file and so i am generating hash in client using javscript crypto-js.
The problem comes when later in java i try to make the request. Apparently the method TimeStampRequestGenerator.generate needs a byte[] parameter that in examples i can se that is a MessageDigest object generated from the content of the file and i can't find the way to use only the hash already generated.
Is it possible to make a request using only the hash of the file already generated ?
Thanks

After hard testing, i have found the solution.
The SHA-256 hash generated in javascript can be used directly in bouncyclaste after some type conversion as follows:
byte[] decodedHex = Hex.decodeHex(digest.toCharArray());
so you can use it as a normal
java.security.MessageDigest
when they are both converted to
byte[]
full code here:
// Get hash code as hexadecimal string (generated by crypto-js)
String digest = servletRequest.getParameter("digest");
// hexadecimal to string decoder
byte[] decodedHex = Hex.decodeHex(digest.toCharArray());
// Timestamp request
TimeStampRequestGenerator reqgen = new TimeStampRequestGenerator();
TimeStampRequest req = reqgen.generate(TSPAlgorithms.SHA256, decodedHex);
byte request[] = req.getEncoded();
...

Related

Password encryption using google/tink

Good day, I have used google/tink to encrypt a password for storing in a DB using these steps :
// 1. Generate the key material.
KeysetHandle keysetHandle =
KeysetHandle.generateNew(AeadKeyTemplates.AES128_GCM);
// 2. Get the primitive.
Aead aead = AeadFactory.getPrimitive(keysetHandle);
// 3. Use the primitive to encrypt a plaintext,
byte[] ciphertext = aead.encrypt(plaintext, aad);
It basically converts password into the bytes, but when i convert it into string to store into the DB, It stores the encrypted password in this format : -�#~�k�D߶{׼�.
But i want to store the password in the format like 11As7737Cs9ue9oo09 using tink encryption.
Is there any way to do it?
Manish, you might not want to encrypt the passwords. You want to hash them. Tink doesn't support password hashing yet, but we can add support if there's enough interest.
Could you please file for a feature request at https://github.com/google/tink/issues/new?
I agree with everyone here that you SHOULD NOT store passwords in the clear.
However, to answer your question because I think it's a common problem when you get some cipher text and the string is unreadable. Say you wanted to store non password data encrypted, and readable. You would need to Base64 encode your cipher text.
When you retrieve your Base64 encoded data back from the database, you would then need to Base64 decode the String and then run it through your decryption process. Building on your example,
String readable = new String(java.util.Base64.getEncoder().encode(cipherText));
byte[] bytesToDecrypt = java.util.Base64.getDecoder().decode(readable.getBytes());

How to decrypt a JWT, in java, which is encrypted with JWE when the encrypted token is present in form of String?

I have a token in String format such as:
eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhHQ00ifQ.K52jFwAQJH-DxMhtaq7sg5tMuot_mT5dm1DR_01wj6ZUQQhJFO02vPI44W5nDjC5C_v4pW1UiJa3cwb5y2Rd9kSvb0ZxAqGX9c4Z4zouRU57729ML3V05UArUhck9ZvssfkDW1VclingL8LfagRUs2z95UkwhiZyaKpmrgqpKX8azQFGNLBvEjXnxxoDFZIYwHOno290HOpig3aUsDxhsioweiXbeLXxLeRsivaLwUWRUZfHRC_HGAo8KSF4gQZmeJtRgai5mz6qgbVkg7jPQyZFtM5_ul0UKHE2y0AtWm8IzDE_rbAV14OCRZJ6n38X5urVFFE5sdphdGsNlA.gjI_RIFWZXJwaO9R.oaE5a-z0N1MW9FBkhKeKeFa5e7hxVXOuANZsNmBYYT8G_xlXkMD0nz4fIaGtuWd3t9Xp-kufvvfD-xOnAs2SBX_Y1kYGPto4mibBjIrXQEjDsKyKwndxzrutN9csmFwqWhx1sLHMpJkgsnfLTi9yWBPKH5Krx23IhoDGoSfqOquuhxn0y0WkuqH1R3z-fluUs6sxx9qx6NFVS1NRQ-LVn9sWT5yx8m9AQ_ng8MBWz2BfBTV0tjliV74ogNDikNXTAkD9rsWFV0IX4IpA.sOLijuVySaKI-FYUaBywpg
Now I want to decrypt this String through some java library and ultimately want to access the payload. Anyone done this so far ?
The assertion you shared with us is a JWE serialized in its compact representation. It has 5 parts separated by a dot (.) which are:
Part 1: the header (eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhHQ00ifQ)
Part 2: the encrypted key - depending on the algorithm, it may be an empty string - (K52jFwAQJH-DxMhtaq7sg5tMuot_mT5dm1DR_01wj6ZUQQhJFO02vPI44W5nDjC5C_v4pW1UiJa3cwb5y2Rd9kSvb0ZxAqGX9c4Z4zouRU57729ML3V05UArUhck9ZvssfkDW1VclingL8LfagRUs2z95UkwhiZyaKpmrgqpKX8azQFGNLBvEjXnxxoDFZIYwHOno290HOpig3aUsDxhsioweiXbeLXxLeRsivaLwUWRUZfHRC_HGAo8KSF4gQZmeJtRgai5mz6qgbVkg7jPQyZFtM5_ul0UKHE2y0AtWm8IzDE_rbAV14OCRZJ6n38X5urVFFE5sdphdGsNlA)
Part 3: the initialisation vector - IV depending on the algorithm, it may be an empty string - (gjI_RIFWZXJwaO9R)
Part 4: the cyphertext (oaE5a-z0N1MW9FBkhKeKeFa5e7hxVXOuANZsNmBYYT8G_xlXkMD0nz4fIaGtuWd3t9Xp-kufvvfD-xOnAs2SBX_Y1kYGPto4mibBjIrXQEjDsKyKwndxzrutN9csmFwqWhx1sLHMpJkgsnfLTi9yWBPKH5Krx23IhoDGoSfqOquuhxn0y0WkuqH1R3z-fluUs6sxx9qx6NFVS1NRQ-LVn9sWT5yx8m9AQ_ng8MBWz2BfBTV0tjliV74ogNDikNXTAkD9rsWFV0IX4IpA)
Part 5: the Additional Authentication Data - AAD - (sOLijuVySaKI-FYUaBywpg)
The header indicates at least the
Key Encryption Algorithm (alg) used to encrypt the content encryption key (CEK)
Content Encryption Algorithm (enc) used in conjunction with the CEK to encrypt the content.
In your case, The alg is RSA-OAEP and the enc is A128GCM.
According to these algorithm, you should have a RSA private key to decrypt the CEK and then use it to decrypt the cyphertext.
https://jwt.io mentioned in the accepted answer will not be useful as it does not support JWE, but JWS. The result shown with a JWE input will not give you the decrypted payload.
However, the https://connect2id.com/products/nimbus-jose-jwt resource will help you as it seems that the algorithms used for your token are supported.
You probably don't necessarily need a library:
String token = eyJ....;
String[] splitToken = JWTEncoded.split("\\.");
// splitToken[0] is the header, splitToken[1] is the payload and
// splitToken[2] is the signature
byte[] decodedBytes = Base64.decode(splitToken[1], Base64.URL_SAFE);
// You don't have to convert it to string but it really depends on what type
// data you expect
String payload = new String(decodedBytes, "UTF-8");
https://jwt.io has a nice little decrypter for you to test data
In regards to JWE the only library I could find is this and an example to unencrypted JWE tokens can be found at the bottom of this page.
Note: I haven't tested this library so I won't be of much use beyond this, but it seems fairly straight forward.

Hashing using md5 and sign using private certificate

I have a requirement wherein I have to generate a URL where one of the parameter is signature and signature has to be generated using below requirement in a Java Application:
The other 4 URL parameter values should be hashed (in the order specified below) using MD5 and sign using the private certificate. (The signature will be DER-encoded PKCS #1 block as defined in RSA Laboratory's Public Key Cryptography Standards Note #1.) The resulting digest should be converted to ASCII character set using base64 and then encoded to comply with HTTP URL character set limitations.
Order Parameter
1 [queryparameter1]
2.. [queryparameter …] *
3 Expiration
The final url should look something like
https://<ServerName>:<Port>/imageRet/pod?ID=123456789&build=XHB&date=201102151326&expiration=20110218155523&signature=H767dhghjKJ#23mxi
I have never worked on Cryptography before and hence don't know how to start.
Can somebody help how can this be achived.
This will be the signature code
Signature sig = Signature.getInstance("MD5withRSA");
sig.initSign(privateKey);
sig.update(canonicalize(params));
byte signature[] = sig.sign();
String signatureB64UrlEncoded = Base64.getUrlEncoder().encodeToString(signature);
Where canonicalize(params) means converting the String parameters of the url to byte[] the way your service specified. You have not given details. This step is not trivial at all because equivalent urls may generate different signatures.
For example
q=hello%20world --> Qazz_tVB-guYai5oW0Eef6BbVP ...
q=hello world --> JJWDEPMQDmffcsjR0dP3vnrkFT ...
An example implementation, but surely not valid...
//Convert params[] to byte[] converting each String to byte with default charset and concatenating results
public byte[] canonicalize(String params[] ) throws IOException{
final ByteArrayOutputStream out = new ByteArrayOutputStream();
for (String param: params){
out.write(param.getBytes());
}
return out.toByteArray();
}
Take a look at Amazon AWS to see an example of how canonicalize a URL
If you finally decide to use a more secure algorithm, simply replace MD5withRSA with for example SHA256withRSA

Encrypt in java, decrypt in node.js

I need to encrypt in java and decrypt with node.js. The decryption result is corrupted.
Here is the java code:
public String encrypt(SecretKey key, String message){
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] stringBytes = message.getBytes("UTF8");
byte[] raw = cipher.doFinal(stringBytes);
// converts to base64 for easier display.
BASE64Encoder encoder = new BASE64Encoder();
String base64 = encoder.encode(raw);
return base64;
}
Here is the node.js code:
AEse3SCrypt.decrypt = function(cryptkey, encryptdata) {
encryptdata = new Buffer(encryptdata, 'base64').toString('binary');
var decipher = crypto.createDecipher('aes-128-cbc', cryptkey);
decipher.setAutoPadding(false);
var decoded = decipher.update(encryptdata);
decoded += decipher.final();
return decoded;
}
As a key I use: "[B#4ec6948c"
The jave encrypted result is: "dfGiiHZi8wYBnDetNhneBw=="<br>
The node.js result is garbich....
In java I use "PKCS5Padding". What should be done in node.js regarding padding? I made setAutoPadding(false). If I don't do it I get error decipher fail. (only from node.js version 0.8).
I tried to remove utf8 encoding from the java in order to be complementary with the node.js but it didn't work.
Any idea what is wrong?
As a key I use: "[B#4ec6948c"
That sounds very much like you're just calling toString() on a byte array. That's not giving you the data within the byte array - it's just the default implementation of Object.toString(), called on a byte array.
Try using Arrays.toString(key) to print out the key.
If you were using that broken key value in the node.js code, it's no wonder it's giving you garbage back.
I tried to remove utf8 encoding from the java in order to be complementary with the node.js
That's absolutely the wrong approach. Instead, you should work out how to make the node.js code interpret the plaintext data as UTF-8 encoded text. Fundamentally, strings are character data and encryption acts on binary data - you need a way to bridge the gap, and UTF-8 is an entirely reasonable way of doing so. The initial result of the decryption in node.js should be binary data, which you then "decode" to text via UTF-8.
I'm afraid I don't know enough about the padding side to comment on that.

Retrieve encapsulated content from Bouncy Castle's CMSAuthenticatedData [Java]

I'm using the CMSAuthenticatedData from the Bouncy Castle library, version 146. I can create it correctly, verified by inspecting the ASN.1 dump, but I can't seem to retrieve the content.
The authenticated data object is created with a generator, like this:
CMSAuthenticatedDataGenerator generator = new CMSAuthenticatedDataGenerator();
CMSProcessableByteArray myContent = new CMSProcessableByteArray(myBytes);
CMSAuthenticatedData cmsData = generator.generate(myContent, myMacCalculator);
cmsData is then serialized with .getEncoded(), sent to the server, and deserialized with the byte[] constructor. From the RFC, I see myBytes should be in the encapContentInfo field inside the AuthenticatedData object, but I can't get it. Here's what I've tried so far:
// The original byte array I want to retrieve is 633 bytes long.
cmsData.getEncoded();
// returns ASN.1 for authData OID and AuthenticatedData object. Size: 724
cmsData.getContentInfo();
// Same as cmsData.getEncoded(). Size: 724
cmsData.getContentInfo().getContent().getDERObject().getEncoded();
// returns ASN.1 for AuthenticatedData object. Size: 703
So, is this even possible, or should I roll out my own implementation, parsing the ASN.1 byte array?
After weeks of research, I found a solution using org.bouncycastle.asn1.cms.AuthenticatedData:
CMSAuthenticatedData cmsData; // <- this is the object created.
byte[] cmsBytes = cmsData.getContentInfo().getContent().getDERObject().getEncoded();
ASN1Sequence byteSeq = (ASN1Sequence) ASN1Object.fromByteArray(rawAuthenticatedDataBytes)
AuthenticatedData authData = new AuthenticatedData(byteSeq);
byte[] contentBytes = authData.getEncapsulatedContentInfo().getContent().getDERObject().getEncoded()
I sure hope this is not the simplest way, but it was the only one I found.

Categories

Resources