Is not so clear to me how to check and parse value passed by this partial response envelope in SAML 2.0:
<dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
<dsig:SignedInfo><dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#WithComments"/><dsig:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<dsig:Reference URI="#ID_ce8c62aa-08e4-4a21-a89a-af4fbd7a9f50">
<dsig:Transforms><dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<dsig:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<dsig:DigestValue>ImUVGjTf7WTCmboAbAtjx7WKQhI=</dsig:DigestValue>
</dsig:Reference>
</dsig:SignedInfo>
<dsig:SignatureValue>CDk+O/3PPh57l84pjFW0xwiPYJ+yinYJciBowT3nkPaAXeMYCH1AopZl7ZP+swPiK+oYuW9STPSlJVuEuDao5VbSU2WlQR7Ed9nZMt9PNY19/eKtkAqbMk01ZY8YH6OyTQm17w6IzNRbY4sJcHSRz9eDUsTzAYVhV9PEBgT1ouZsghklMCe0iYBjK5LmRS88jGmCN5sZ5+L8+KimTCakWSJ8CLntEAFx1SBL50Or4e8j6nHiW7g==</dsig:SignatureValue>
<dsig:KeyInfo>
<dsig:KeyValue>
<dsig:RSAKeyValue>
<dsig:Modulus>4Gvzu2dCYGhdWr9Er/WtgbWRqAR798IPCfAubx8NeBKG/X6P7sM91zbD2LEH4tJS2vkMCnQFidoLdeh1SHp7+GLHnVsgTcj6NPOit0EOHz10tdRmFMwoRCh5hcMFEisFUgSdaS8bO2wSXBmLENfLDUOSYKKLP0JGtTqnAZ0A99UNrVWKemx/EnHopH+Q7M+zmbj8VWFVlCK6rDfXJLUBr+kGSlw==</dsig:Modulus>
<dsig:Exponent>AQAB</dsig:Exponent>
</dsig:RSAKeyValue>
</dsig:KeyValue>
</dsig:KeyInfo>
</dsig:Signature>
So basically the RSAKeyValue should contain the "public key" to read the DigestedValue?
So what's the purpose of the Signature value?
I would like to implement a Java class to decrypt (I have the proper keystore and pass to do that...). Please point me in the right direction.
As written in the comment, it's an XML signature. The signature allows you to validate the XML has been signed by a trusted party and the element hasn't been modified. So you can trust the SAML response is really from the IdP you can trust. It is not encryption.
I would like to implement a Java class to decrypt
As I stated there's nothing to decrypt, you can only validate integrity of the signed XML element.
For that I suggest you use an out of box library to process the XML (it will be boring to implement all canonization options, etc..). I suggest you use an out of box library ( OpenSAML, spring-security-saml2) to validate the signature.
if you want to do it yourself, just read search/about the XML signatures.
What you have there:
<dsig:Reference URI="#ID_ce8c62aa-08e4-4a21-a89a-af4fbd7a9f50">
There must be an element in your XML with id attribute of "#ID_ce8c62aa-08e4-4a21-a89a-af4fbd7a9f50" and the signature ensures integrity of the refered XML element. Make sure the signature is refered to the whole SAML message or an assertion element. If not, you're code would be prone to signature injection attacks. That's why I suggest you use a mature library for that.
<dsig:DigestValue>ImUVGjTf7WTCmboAbAtjx7WKQhI=</dsig:DigestValue>
RSA doesn't work with messages of arbitrary (any) length, so a message digest (sha-1 hash) is created and that is signed. The DigestValue is value of the hash created from the signed XML element and its content. (how to create a whole content to be hashed is depending on the parameters stated in the CanonicalizationMethod, Transforms, DigestMethod, you can read about it in the first link)
<dsig:SignatureValue>
This is the RSA/PKCS1.5 signature of the DigestValue
I hope that clarifies your question.
Related
The plain text is signed using java.security.Signature. Below is the code used to sign the plain text
public String getSignature(String plainText) throws Exception
{
KeyStore keyStore = loadKeyStore(); // A local method to read the keystore file from file system.
PrivateKey privateKey = (PrivateKey) keyStore.getKey(KEY_ALIAS_IN_KEYSTORE, KEYSTORE_PASSWORD.toCharArray());
Signature privateSignature = Signature.getInstance(SIGNATUREALGO);
privateSignature.initSign(privateKey);
privateSignature.update(plainText.getBytes("UTF-8"));
byte[] signature = privateSignature.sign();
return String.valueOf(signature);
// KEY_ALIAS_IN_KEYSTORE, KEYSTORE_PASSWORD and SIGNATUREALGO are all constant Strings
}
Note 1: I found online a way to verify the signature using the public key Java Code Examples for java.security.Signature#verify(). But this is not what I require.
Note 2: I also found a ways to encrypt and decrypt as mentioned here RSA Signing and Encryption in Java. But the use case I have in hand is to get the original plain text from a signed data. Is that possible?
No, you can't retrieve the original content from just the signature.
The signature alone does not contain enough information to restore the original clear text, no matter what keys you have access to.
The basic idea of a signature is to send it together with the clear text. That means the clear text will be visible, but the signature can be used to verify that the message was written (or at least signed) by who claims to have done so and has not been tampered with since then.
Signing something is different from encrypting it. The two often uses the same or related technologies and both fall under cryptography.
I need to add two QualifyingPropertiesReference nodes with given URI values into Object within a XadES Signature.
I'm generating an xml Signature which requires to pass a certificate via URL instead of attaching it in KeyInfo element. For this, QualifyingPropertiesReference looks like a good fit, however I could not find a way or an example in wiki/tests that would add this element. Looking at the code, I found XmlQualifyingPropertiesReferenceType, but did not see it being used anywhere. My signing code:
XadesSigningProfile signingProfile =
new XadesBesSigningProfile(keyingDP)
.withBasicSignatureOptions(new BasicSignatureOptions().includeSigningCertificate(SigningCertificateMode.NONE));
XadesSigner signer = signingProfile.newSigner();
Document doc = createDocument(xmlMessage);
DataObjectDesc obj = new DataObjectReference("")
.withTransform(new EnvelopedSignatureTransform());
SignedDataObjects dataObjects = new SignedDataObjects().withSignedDataObject(obj);
signer.sign(dataObjects, doc.getFirstChild());
Basically, I want this kind of Signature structure:
<Signature>
....
<Object>
<QualifyingPropertiesReference URI="some_url"/>
<QualifyingPropertiesReference URI="some_url2"/>
<QualifyingProperties>
....
</Object>
</Signature>
If there's no way, would adding them to doc manually make Signature invalid? Are <Object> contents used for hashing?
xades4j doesn't support QualifyingPropertiesReference for two main reasons: 1) no real use cases for it; 2) XAdES Baseline profiles do not allow it section 6.1 of baseline profiles spec.
That said, I'm not sure your use-case is one for QualifyingPropertiesReference. This element is just a means of pointing to another XML resource where the qualifying properties are present. Maybe you misunderstood it. I don't think it has anything to do with certificates or how to obtain them.
It is ok that a signature doesn't include the certificates needed for validation. In this case the verifier is expected to know how to obtain them. Another option is to add "application-specific" data to the signature, where you pass the URL.
I'm stumped trying to figure out Esig DSS java suite just from docs and source.
(eu.europa.esig.dss.* tree)
We connect to Swedish BankID to sign PDF's and simple plain texts.
Response is a SOAP XML with fields for the signature and an OCSP response.
The end goal is to combine these two parts into a single object "a valid signature" that can be embedded in a PDF (using DSS and PDFbox).
The contents of the BankID Soap fields seems to have the right format for DSS tools:
The signature can be loaded with
DSSDocument sigDoc = new InMemoryDocument(xmlSignature)
SignedDocumentValidator documentValidator = SignedDocumentValidator.fromDocument(sigDoc);
// ...
AdvancedSignature advancedSignature = documentValidator.getSignatures().get(0);
and the OCSP response can be read with
ExternalResourcesOCSPSource source = new ExternalResourcesOCSPSource(ocspBytes);
BasicOCSPResp basicOCSPResp = source.getContainedOCSPResponses().get(0);
I can print out various info from the objects, find embedded certificates etc, so the format seems legit.
Question:
How do I get a valid OCSPToken from the ExternalResourcesOCSPSource?
I keep running in circles trying to combining the two into a single AdvancedSignature (if that's what I can use to embed into a PDF).
An advanced digital signature provided by a third system can not be used to create a valid signed PDF
A PAdES signature is always enveloped into a PDF document, so it is not possible for the signature service to be returning a detached PAdES signature that is considered valid by DSS.
It probably provides a detached CAdES or XAdES signature into the SOAP message that can be processed by DSS( DSS provides a high level API to sign documents using XAdES, CAdES, PAdES and aSiCS formats).
Both formats support embedding the OCSP responses, but it requires to add a TimeStamp too, which make more difficult to build the final format. It could be the reason to use a custom field into the SOAP message to return the OCSP response
XAdES and PAdES are conceptually similar but structurally different. A XAdES signature is XML and PAdES is binary. A XML signature can not be converted to PAdES
PAdES and CAdES use CMS, both are binary and they use ASN.1 syntax. But the signed message is different, CAdES signature is calculated on the entire document (and some othe attributes) and PAdes use certain data of the PDF document. Therefore a cades signature could not be converted to PAdes either.
At the moment I'm receiving messages which are signed with a certificate.
So far so good.
However the certificate contains an attribute PSEUDONYM.
Now the Java runtime doesn't accept it. I get an IO Exception. (When I remove the PSEUDONYM exception is gone )
Does anybody know you to validate these messages as i'm sure that attribute PSEUDONYM is allowed.
C=DE,O=InfoCompany,OU=SoftwareMe,CN=SIGNER,SERIALNUMBER=1,PSEUDONYM=SIGNER
Any ideas how to change the default java validation to allow the PSEUDONYM tag?
Using constructor X500Principal(String name, Map<String,String> keywordMap) allows you to specify custom RDNs in keywordMap. The map's key is a RDN name and the value is a string representation of OID. See Java documentation for details.
I have a servlet and the content type of my request is of type : application-pkcs-7
And how do i decode the request ?
Any ideas ?
I learnt that i can use openssl to decode , but not much docs on that .
That's probably a signature or an encrypted piece of data. It's old name is PKCS-7 (of RSA labs, publicly available standard) but it is also known as CMS (Cryptographic Message Syntax, publicly available RFC). CMS is a container format for different kinds of encryption. You can parse it in Java using the open source Bouncy Castle libraries - "bcmail" in particular, but you probably need some kind of key if it is encrypted. If it is signed, you could simply parse the plain text data from it and ignore the signature, I guess, depends on the application really.
[UPDATE] Since 1.47 the necessary functionality is in the PKIX library of Bouncy Castle.
Should work in this way
CMSSignedData cmsSignedData = new CMSSignedData(byte[] signedData);
CMSProcessable cmsProcessable = cmsSignedData.getSignedContent();
In my case it didn't though, because of unknown tag entry while parsing data