cancel
Showing results for 
Search instead for 
Did you mean: 

verify url secKey

Former Member
0 Kudos

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));

Accepted Solutions (0)

Answers (6)

Answers (6)

former_member545461
Discoverer
0 Kudos

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.

darren_martin
Explorer
0 Kudos

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);

Former Member
0 Kudos

Thanks for sharing this sample.

When I put in my values I always get the error "message-disgest does not match computed value".

Can you give me a hint where to look for a solution?

Regards

Mirco Schöpf

Former Member
0 Kudos

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)

Former Member
0 Kudos

Finally.

I solved the problem. You have to use urldecode for secKey but when creating message2sign bytes you have to DONT use urldecode, you need to create message2sign string from rawurl.

Former Member
0 Kudos

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!

Former Member
0 Kudos

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

Former Member
0 Kudos

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

Former Member
0 Kudos

the line

CMSSignedData csd = new CMSSignedData (new CMSProcessableByteArray (), signature);

must be

CMSSignedData csd = new CMSSignedData (new CMSProcessableByteArray (message2Sign), signature);

Former Member
0 Kudos

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

Former Member
0 Kudos

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.