on 03-28-2006 10:15 PM
Hi,
I need some help implementing a small interface for arcchive link (the http-interface). I want to verify the url using the seckey parameter and the certifiacte the sap-system supplies.
I'am using bouncycastle as security provider but I get an error. The error I get is "error decoding signature bytes". I am not sure if I have to do something with the secKey before I can start the verification.
Has anybody tried this? How do you verify the url?
Code and tipps welcome!!!
Please help.
My Code:
secKey = byte array containing the urldecoded value of the sec-key parameter
MessageDigest md5 = MessageDigest.getInstance("MD5");
byte[] hash= md5.digest(buffer);
java.security.Signature dsa2 = java.security.Signature.getInstance("SHA1withDSA", "BC");
dsa2.initVerify(certificate.getPublicKey());
dsa2.update(hash);
System.out.println("Verification: " + dsa2.verify(secKey));
I found this to be even trickier: the authId SAP sends is similar to this (system name changed): CN%3D55,OU%3DD55,O%3DSAPTrustCommunity,C%3DDE 20200411171741
This part is partially encoded: equal signs are encoded ('=' is %3D), but commas are not encoded. So be careful to only decode / encode parameters individually and pay attention to the mixed mode in the authId parameter.
You can see the message SAP sends in your content server's access log and compare.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I revised java code example on sdn to C# and it works.
Note: In the content server doc for each function it lists parameters of the query string. Last column of this parameters table called Sign (Yes/No) tells which parameters s/b used to build a message for verification. These make of the value message2Sign.
The variable good contains the value of secKey.
Add Reference to BouncyCastle.Crypto
using Org.BouncyCastle;
using System.Text;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.Cms;
byte[] message2Sign = Encoding.Default.GetBytes("E25B5CECB6846E1F4F92C9E9058BC415FDrCN%3DC1120071026161701");
String good = "MIIBlAYJKoZIhvcNAQcCoIIBhTCCAYECAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHATGCAWAwggFcAgEBMBMwDjEMMAoGA1UEAxMDQzExAgEAMAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wNzEwMjYxNDE3MDFaMCMGCSqGSIb3DQEJBDEWBBT/ObaVw5qhQRX5MTMnyVqptXhwnTCBpgYFKw4DAhswgZwCQQEi9Vy1IpGpgBwpby66sV16jIHOJkoJI/blRDbeogY2I+S69a9+JmlAfQEn+ttGqA3jv/QAf98zFtmFpsDwniO1AhUBQNzq3BaLZ3Vj2dGBB5HPZh5eBa0CQHsZv4pNumfHRNhmlbKK9TDgPQrDDnG7F51g1FhTAFvceltg20WjHE/dFaH8jkigzaJDkFI+uV50yGPytGPYmekELzAtAhUBBudqwTj+JNfkpr6BausHDZpqMmUCFC9rWauPQhjYNp4tiHWPmpgw9NXl";
String bad = "MIIBlAYJKoZIhvcNAQcCoIIBhTCCAYECAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHATGCAWAwggFcAgEBMBMwDjEMMAoGA1UEAxMDQzExAgEAMAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wNzEwMTgxMTQxNTVaMCMGCSqGSIb3DQEJBDEWBBS+2xHiq+u4ZssgcURXnsqx+hf5kTCBpgYFKw4DAhswgZwCQQEi9Vy1IpGpgBwpby66sV16jIHOJkoJI/blRDbeogY2I+S69a9+JmlAfQEn+ttGqA3jv/QAf98zFtmFpsDwniO1AhUBQNzq3BaLZ3Vj2dGBB5HPZh5eBa0CQHsZv4pNumfHRNhmlbKK9TDgPQrDDnG7F51g1FhTAFvceltg20WjHE/dFaH8jkigzaJDkFI+uV50yGPytGPYmekELzAtAhUBOKbZGs22bN+iMQ8UkPL4vaPewDwCFFof2Pv04DXMDPj2SnZ7wMcCKTfH";
byte[] signature = Convert.FromBase64String(good);
byte[] certBytes = System.IO.File.ReadAllBytes(@"cert.certs"); // Path To cerficate
X509CertificateParser certParser = new X509CertificateParser();
X509Certificate cert = certParser.ReadCertificate(certBytes);
Org.BouncyCastle.Crypto.AsymmetricKeyParameter pk = cert.GetPublicKey();
CmsProcessable processable = new CmsProcessableByteArray(message2Sign);
CmsSignedData s = new CmsSignedData(processable, signature);
SignerInformationStore signers = s.GetSignerInfos();
System.Collections.ICollection c = signers.GetSigners();
System.Collections.IEnumerator it = c.GetEnumerator();
it.MoveNext();
SignerInformation signer = (SignerInformation)it.Current;
// verification
bool test2 = signer.Verify(cert);
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I've got the same problem. But I'm working with c#.
I'm trying to implement SAP HTTP interface but i'm stuck on secKey validation.
I try this;
byte[] message2Sign = Encoding.Default.GetBytes("ZEF8BC1255A0921ED4ACCF82E0D93E80D1rCN=ID3,OU=I0120003411,OU=SAPWebAS,O=SAPTrustCommunity,C=DE20150226175037");
String good = "MIIBUgYJKoZIhvcNAQcCoIIBQzCCAT8CAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHATGCAR4wggEaAgEBMG8wZDELMAkGA1UEBhMCREUxHDAaBgNVBAoTE1NBUCBUcnVzdCBDb21tdW5pdHkxEzARBgNVBAsTClNBUCBXZWIgQVMxFDASBgNVBAsTC0kwMTIwMDAzNDExMQwwCgYDVQQDEwNJRDMCByARCBgTIEcwCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTE1MDIyNjE1NTAzN1owIwYJKoZIhvcNAQkEMRYEFIfokqbPQrTgvjOIVDXOmJTa82A/MAkGByqGSM44BAMELzAtAhREfjykVVBMcp81DuMU4jQtR+wzWQIVAIjwJujz64iVjncjETdU00iE/kI2";
byte[] signature = Convert.FromBase64String(good);
byte[] certBytes = System.IO.File.ReadAllBytes(@"cr.cer"); // Path To cerficate
X509CertificateParser certParser = new X509CertificateParser();
X509Certificate cert = certParser.ReadCertificate(certBytes);
Org.BouncyCastle.Crypto.AsymmetricKeyParameter pk = cert.GetPublicKey();
CmsProcessable processable = new CmsProcessableByteArray(message2Sign);
CmsSignedData s = new CmsSignedData(processable, signature);
SignerInformationStore signers = s.GetSignerInfos();
System.Collections.ICollection c = signers.GetSigners();
System.Collections.IEnumerator it = c.GetEnumerator();
it.MoveNext();
SignerInformation signer = (SignerInformation)it.Current;
// verification
bool test2 = signer.Verify(cert);
and also try this
String good = "MIIBUgYJKoZIhvcNAQcCoIIBQzCCAT8CAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHATGCAR4wggEaAgEBMG8wZDELMAkGA1UEBhMCREUxHDAaBgNVBAoTE1NBUCBUcnVzdCBDb21tdW5pdHkxEzARBgNVBAsTClNBUCBXZWIgQVMxFDASBgNVBAsTC0kwMTIwMDAzNDExMQwwCgYDVQQDEwNJRDMCByARCBgTIEcwCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTE1MDIyNjE1NTAzN1owIwYJKoZIhvcNAQkEMRYEFIfokqbPQrTgvjOIVDXOmJTa82A/MAkGByqGSM44BAMELzAtAhREfjykVVBMcp81DuMU4jQtR+wzWQIVAIjwJujz64iVjncjETdU00iE/kI2";
byte[] sk = Convert.FromBase64String(good);
byte[] auth = System.Text.Encoding.ASCII.GetBytes("ZEF8BC1255A0921ED4ACCF82E0D93E80D1rCN=ID3,OU=I0120003411,OU=SAPWebAS,O=SAPTrustCommunity,C=DE20150226175037");
byte[] certBytes = System.IO.File.ReadAllBytes(@"cr.cer"); // Path To cerficate
X509CertificateParser certParser = new X509CertificateParser();
X509Certificate cert = certParser.ReadCertificate(certBytes);
Org.BouncyCastle.Crypto.AsymmetricKeyParameter pk = cert.GetPublicKey();
Org.BouncyCastle.Cms.CmsSignedData csd = new Org.BouncyCastle.Cms.CmsSignedData(new Org.BouncyCastle.Cms.CmsProcessableByteArray(auth), sk);
Org.BouncyCastle.Cms.SignerInformationStore store = csd.GetSignerInfos();
System.Collections.ICollection signers = store.GetSigners();
foreach (Org.BouncyCastle.Cms.SignerInformation sinfo in signers)
{
try
{
if (!sinfo.Verify(cert))
Console.WriteLine("verified.");
}
catch (Exception ex)
{
Console.WriteLine("not verified.");
}}
but i always get "message-digest attribute value does not match calculated value" exception.
Do you have any idea how i correct this?
I'm creating message2sign variable in this order;
ContRep+DocId+AccessMode+AuthId+Expiration(as told in documentation)
Hi Torsten, since you've been working with the HTTP archive I wondered if I might pick your brains
I'm trying to write a .NET (or Java, I'm not picky) webservice that will retrieve documents from the SAP Content Server.
I understand that I need to build a URL to the content server to retrieve each document, and that part of this URL is a security key 'secKey'.
I've seen such documents as:
http://help.sap.com/saphelp_nw2004s/helpdata/en/f5/9561c8f3b111d1955b0000e82deb58/content.htm
http://help.sap.com/saphelp_nw2004s/helpdata/en/9b/e8c192eaf811d195580000e82deb58/content.htm
And everything seems fine, except for how to create the 'secKey'. I can hash the URL parameters as required, but I don't know how to sign it - how do I obtain the sender's private key in order to do this?
Any help with this would be greatly appreciated!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi,
Thanks for the replies and thanks for the code examples! I do get the same error as Brian. I use the same version of BC and JRE/JDK.
I will keep trying.
cu
Torsten
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Torsten,
I was able to get an answer to this in a post to the Bouncy Castle support list. Apparently, the "no such algorithm" error is caused by a bug in the most recent version of BC. I was pointed to a new beta version, 133b06, and it worked great.
You can download it from:
http://www.bouncycastle.org/betas
Good luck!
Brian
the line
CMSSignedData csd = new CMSSignedData (new CMSProcessableByteArray (), signature);
must be
CMSSignedData csd = new CMSSignedData (new CMSProcessableByteArray (message2Sign), signature);
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Ernesto,
I am using code similar to what you provided for verifying the secKey and I am getting an error like the following when executing the signer.verify() method:
java.security.NoSuchAlgorithmException: no such algorithm: SHA
1with1.3.14.3.2.27 for provider BC
I am running JDK 1.4.2 with Bouncy Castle 1.32.
Did either of you have any luck getting this to work?
Thanks,
Brian
Hello,
I'm also implementing the http-interface.
It's the code with bouncy castle:
byte [] publicKey = ...;
byte [] signature = ...; // the value of the secKey parameter
byte [] message2Sign = ...; // bytes of the string used for calculate the signature. It's the summarized of some parameters. And it must be encoding like a URL (page 11 of the specification).
CertificateFactory cf = CertificateFactory.getInstance ("X.509", "BC");
X509Certificate certificate = (X509Certificate) cf.generateCertificate (new ByteArrayInputStream (publicKey ));
CMSSignedData csd = new CMSSignedData (new CMSProcessableByteArray (), signature);
SignerInformationStore signerInfos = csd.getSignerInfos ();
Collection signers = signerInfos.getSigners();
boolean verified = true;
SignerInformation signer;
for (Iterator sit = signers.iterator(); verified && sit.hasNext();) {
signer = (SignerInformation) sit.next ();
verified = verified && signer.verify (certificate, "BC");
}
return verified;
Regards,
Ernesto.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
84 | |
23 | |
11 | |
9 | |
8 | |
5 | |
5 | |
5 | |
5 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.