Creating PKCS7 signature from etoken - java

I am trying to generate a digital signature using an etoken.
I am using BouncyCastle library and the signature is being generated.
The problem is that I want it in pkcs7 format which also contains tags like '-----BEGIN PKCS7-----' and ends with '-----END PKCS7-----'.But the signature that I generate doesn't contain these tags.
I am not sure where I'm going wrong.
Here is my code..
CMSProcessable content = new CMSProcessableByteArray(contentbytes);
CMSSignedData signedData = signGen.generate(content, securityProviderName);
byte[] signeddata = signedData.getEncoded();
BASE64Encoder encoder = new BASE64Encoder();
digitalSignature = encoder.encode(signeddata);
Now I need the data to be in pkcs7 format.Is there anything wrong with the code? Or do I need to add anything to this? Please help.. Thank you.

PKCS#7, usually called CMS (Cryptographic Message Syntax) is a container format that is specified using ASN.1 and encoded using BER/DER (Basic/Distinguished Encoding Rules). BER/DER are methods of performing binary encoding.
What you are talking about is PEM format, which was specified for Privacy Enhanced Mail. It is sometimes also called an ASCII armor as it makes it possible for binary data to be send over text interfaces. It consists of a header and footer that also identify the data, as well as the encoding to base 64 of the DER encoded blob.
What you can do is to implement the header and footer generation yourself, or you can take a look at the PemWriter class within the Bouncy Castle for Java functionality. The specifications of the format can be found here.

Related

how to specify signature length for java.security.Signature sign method

For my application, I'm trying to sign some byte contents using java.security.Signature class. The problem I'm having is that signature is never generated at a fixed length. For instance, sometimes it is generated at a length of 135, 136 or 137 bytes. Is there a way to specify the length or some padding at the end? Any other ideas or comments are appreciated.
private byte[] ecdsaSign(ECPrivateKey key, byte[] content) throws Exception {
Signature ecdsaSign = Signature.getInstance("SHA256withECDSA", "SC");
ecdsaSign.initSign(key);
ecdsaSign.update(content);
byte[] signature = ecdsaSign.sign();
return signature;
}
For ECDSA Java crypto uses the ASN.1 DER encoding standardized by X9.62, SEC1 and rfc 3279 sec 2.2.3, which varies slightly in length. This is covered in more detail on another Stack: https://crypto.stackexchange.com/questions/1795/how-can-i-convert-a-der-ecdsa-signature-to-ASN.1 and https://crypto.stackexchange.com/questions/33095/shouldnt-a-signature-using-ecdsa-be-exactly-96-bytes-not-102-or-103 and https://crypto.stackexchange.com/questions/37528/why-do-openssl-elliptic-curve-digital-signatures-differ-by-one-byte
This is also true for DSA, but not RSA, where signatures (and cryptograms since RSA supports both signature and encryption) are fixed length for a given key, as defined by I2OS and OS2I in PKCS1.
If you want a different encoding, such as the fixed-length one used by PKCS11 (and your provider name "SC" suggests that possibility), you must convert it.
Added 2019-10: you no longer have to do it yourself in Java; BouncyCastle since 1.61 (2019-02) correctly supports this, as does SunEC in Java 9 up (2018-12). See later near-dupe Java ECDSAwithSHA256 signature with inconsistent length .

How to check whether a PKCS#7 signature valid or not in Java

I have been doing this task for more than 3 days, and finally I realised that I need some help. I have 2 files - a PKCS#7 file(base64 encoded) and a file which was signed by the PKCS#7(say, pdf). My question is how can I check whether the sign is right or not and the file is intact. I ended up with this algorithm:
Transform a pdf file to base64
Check all the certificates in PKCS#7(whether some is out of date, or not valid)
Get a hash from a pdf file(applying a specific hash algorithm)
Get a hash from a PKCS#7 file(applying the same algorithm)
Finally check these 2 hashs
I hope it's the right order and with it's help I can perform my task and finally check integrity. But I don't know how to perform it using Java. The library I supposed to use is Bouncy Castle. Before it, I just processed the PKCS#7 file like this:
String rawString = ASN1ObjectIdentifier.fromByteArray(bytesArray).toString();
String rawStringForSurname = rawString.substring(rawString.indexOf("2.5.4.4,") + 9, rawString.length());
String signSurname = rawStringForSurname.substring(0, rawStringForSurname.indexOf("]"));
String rawStringForGivenName = rawString.substring(rawString.indexOf("2.5.4.42,") + 10, rawString.length());
String signGivenName = rawStringForGivenName.substring(0, rawStringForGivenName.indexOf("]"));
I guess this approach is awful. Getting a String from the whole raw ASN.1 is a terrible idea, though it's the only solution I did by myself. And using this approach I can not somehow "compare" the pdf and the PKCS#7 somehow. How can I perform it using X509Cerftificate, SignedData and other feautures from Bouncy Castle? Please correct me if I wrong about the order of actions and the actions itself.

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.

Generate CMSSignedData with no private key in JAVA

I'm currently trying to generate a CMSSignedData using only a certificate data and a signed data which is generated from an external software (so I don't have access to the private key and the signature generation is transparent for me). What i need is the encoded data to add it to a SMIME signature content.
Searching on web I find out a solution with BouncyCastle that uses the private key and the data to be signed to get a CMSSignedData. But it don't fix to my problem because I don't have access to private key and the signature is already generated.
Is there any way to create a CMS object using only the certificate data, the public key and the previously generated signature?
Any approach or library i can use or try?
CMS (Cryptographic Message Syntax) is specified in RFC 5652. The SignedData type is an ASN.1 structure, which basically consists of the signed data (encapContentInfo), the signature certificate (and chain) and the signature itself (part of signerInfos):
SignedData ::= SEQUENCE {
version CMSVersion,
digestAlgorithms DigestAlgorithmIdentifiers,
encapContentInfo EncapsulatedContentInfo,
certificates [0] IMPLICIT CertificateSet OPTIONAL,
crls [1] IMPLICIT RevocationInfoChoices OPTIONAL,
signerInfos SignerInfos }
SignerInfo ::= SEQUENCE {
version CMSVersion,
sid SignerIdentifier,
digestAlgorithm DigestAlgorithmIdentifier,
signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL,
signatureAlgorithm SignatureAlgorithmIdentifier,
signature SignatureValue,
unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL }
So, what you have to do now is to create this ASN.1 structure out of the data you have. If you don't already know the algorithms that were used for the signature, you can certainly obtain that information from the operator of the external signing software.
Bouncy Castle is generally a good choice for ASN.1 encoding and in addition you can use the source code of Bouncy Castle that normally creates a CMSSignedData object (CMSSignedDataGenerator) as a template.

How to validate a Timestamp from an ASN.1 encoded byte stream in Java

I'm trying to validate a timestamp from an ASN.1 encoded byte stream in Java.
I'm using the bouncycastle package.
I'm creating the TimeStampToken from the encoded byte I got from the timestampserver.
TimeStampToken testTsToken = new TimeStampToken(new CMSSignedData(encodedByte));
For validation there is the following function.
testTsToken.validate(SignerInformationVerifier);
testTsToken.validate(X509Certificate, String);
I'm now wondering how do I get those Parameters?
How can I create a SignerInformationVerifier or a X509Certificate?.
I would appreciate any help because I'm stuck on this issue for days now :/
My problem was that when asking for the timestamp i forgot to ask for a certificate. That's why I couldn't validate.

Categories

Resources