Verifying signed message of SAP Content Server with OpenSSL or PHP

716 views Asked by At

I have a similar problem as described in failed to verify a dsawithSha1 signed message against a DSA public key in python/m2crypto. Sadly the asker found a solution with OpenSSL but doesn't shared his knowledge.

I want to implement the verification of a signed message in PHP or - as a fallback - with OpenSSL.

I have the following certificate, which is originaly delivered as PKCS#7, which I converted to X.509 in PEM format ($pubKey in PHP below):

-----BEGIN CERTIFICATE-----
MIIC+zCCArsCByAUBAcGQhAwCQYHKoZIzjgEAzBkMQswCQYDVQQGEwJERTEcMBoG
A1UEChMTU0FQIFRydXN0IENvbW11bml0eTETMBEGA1UECxMKU0FQIFdlYiBBUzEU
MBIGA1UECxMLSTAwMjAxODQ4OTAxDDAKBgNVBAMTA1NFMjAeFw0xNDA0MDcwNjQy
MTBaFw0zODAxMDEwMDAwMDFaMGQxCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNTQVAg
VHJ1c3QgQ29tbXVuaXR5MRMwEQYDVQQLEwpTQVAgV2ViIEFTMRQwEgYDVQQLEwtJ
MDAyMDE4NDg5MDEMMAoGA1UEAxMDU0UyMIIBtzCCASsGByqGSM44BAEwggEeAoGB
AP/jA7UNBUG5dqASOkGZ0+JLiKqwhHIEqKarqiuCGvho3Fwc8OzWxVr3cyGomHdw
q0UkwvMROGhGsg0DOvJc0u7wY4BKmR1gUkOwg6DzX0JZbZ/hMWW/wzixiC+LtoGD
p3DVvCzLbZ9ujaI4NhkhCaw/OPjli7Q0TbPPNxT15wmdAhUApZDvRmv7txM8IowT
JCJa0igBuw8CgYBqPNctSVdgszu2BJf9rYdafUUN6BP7jCY4JxGPgPqYkEdDsLAs
RdPfLohhjHUD8z6F0XBLvQBuwo+0ShAa3KZ8wEOYUAZ2IyJmoE7OBmW3uIcZ/s7g
jwftGABsfx2uJ8s2mbV6Mak++dw8Yn0WvsTWBD9NaI4cwn3Kw92GSNpQvgOBhQAC
gYEAisABEC7nuf3Stibic8RySBMbmg3CYLvX2N2MgQZcSC8dZ6WI6n39vtKDOT7k
ckS0ogDNFpWvfMZTjv2ZzyJkpcUbKI3K/yjWl5NeGRGuAM7wMZbpkPTe4eNWaW4k
exJWjWCSFz3W11XKgq7xDKzkTeb2oV+IfehxoTdTrJ1ZA2kwCQYHKoZIzjgEAwMv
ADAsAhQWUSemKo/Wa2y0asoNraOFlIE1DwIUGGM/Ll1zejSh5qzQVOrr1MzJRWI=
-----END CERTIFICATE-----

and the signed message:

MIIBUgYJKoZIhvcNAQcCoIIBQzCCAT8CAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHATGCAR4wggEaAgEBMG8wZDELMAkGA1UEBhMCREUxHDAaBgNVBAoTE1NBUCBUcnVzdCBDb21tdW5pdHkxEzARBgNVBAsTClNBUCBXZWIgQVMxFDASBgNVBAsTC0kwMDIwMTg0ODkwMQwwCgYDVQQDEwNTRTICByAUBAcGQhAwCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTE0MTEyNDA4MTYxM1owIwYJKoZIhvcNAQkEMRYEFCId8O7H%2Bwd1LCNg6ZiNNU6TZtJqMAkGByqGSM44BAMELzAtAhR6ELQT%2B8ueklNmizCrSjvG8vVTAwIVAJCi5juWEEBJeH2GUH4KtA8sRrIK

which is translated to a binary format via urldecode and base64_decode, which is stored in DER format in a file named seckey.der ($secKeyDer in PHP below)

With OpenSSL I can view the contents of the ASN.1 structure:

openssl asn1parse -in seckey.der -inform der

which results in:

    0:d=0  hl=4 l= 338 cons: SEQUENCE
    4:d=1  hl=2 l=   9 prim: OBJECT            :pkcs7-signedData
   15:d=1  hl=4 l= 323 cons: cont [ 0 ]
   19:d=2  hl=4 l= 319 cons: SEQUENCE
   23:d=3  hl=2 l=   1 prim: INTEGER           :01
   26:d=3  hl=2 l=  11 cons: SET
   28:d=4  hl=2 l=   9 cons: SEQUENCE
   30:d=5  hl=2 l=   5 prim: OBJECT            :sha1
   37:d=5  hl=2 l=   0 prim: NULL
   39:d=3  hl=2 l=  11 cons: SEQUENCE
   41:d=4  hl=2 l=   9 prim: OBJECT            :pkcs7-data
   52:d=3  hl=4 l= 286 cons: SET
   56:d=4  hl=4 l= 282 cons: SEQUENCE
   60:d=5  hl=2 l=   1 prim: INTEGER           :01
   63:d=5  hl=2 l= 111 cons: SEQUENCE
   65:d=6  hl=2 l= 100 cons: SEQUENCE
   67:d=7  hl=2 l=  11 cons: SET
   69:d=8  hl=2 l=   9 cons: SEQUENCE
   71:d=9  hl=2 l=   3 prim: OBJECT            :countryName
   76:d=9  hl=2 l=   2 prim: PRINTABLESTRING   :DE
   80:d=7  hl=2 l=  28 cons: SET
   82:d=8  hl=2 l=  26 cons: SEQUENCE
   84:d=9  hl=2 l=   3 prim: OBJECT            :organizationName
   89:d=9  hl=2 l=  19 prim: PRINTABLESTRING   :SAP Trust Community
  110:d=7  hl=2 l=  19 cons: SET
  112:d=8  hl=2 l=  17 cons: SEQUENCE
  114:d=9  hl=2 l=   3 prim: OBJECT            :organizationalUnitName
  119:d=9  hl=2 l=  10 prim: PRINTABLESTRING   :SAP Web AS
  131:d=7  hl=2 l=  20 cons: SET
  133:d=8  hl=2 l=  18 cons: SEQUENCE
  135:d=9  hl=2 l=   3 prim: OBJECT            :organizationalUnitName
  140:d=9  hl=2 l=  11 prim: PRINTABLESTRING   :I0020184890
  153:d=7  hl=2 l=  12 cons: SET
  155:d=8  hl=2 l=  10 cons: SEQUENCE
  157:d=9  hl=2 l=   3 prim: OBJECT            :commonName
  162:d=9  hl=2 l=   3 prim: PRINTABLESTRING   :SE2
  167:d=6  hl=2 l=   7 prim: INTEGER           :20140407064210
  176:d=5  hl=2 l=   9 cons: SEQUENCE
  178:d=6  hl=2 l=   5 prim: OBJECT            :sha1
  185:d=6  hl=2 l=   0 prim: NULL
  187:d=5  hl=2 l=  93 cons: cont [ 0 ]
  189:d=6  hl=2 l=  24 cons: SEQUENCE
  191:d=7  hl=2 l=   9 prim: OBJECT            :contentType
  202:d=7  hl=2 l=  11 cons: SET
  204:d=8  hl=2 l=   9 prim: OBJECT            :pkcs7-data
  215:d=6  hl=2 l=  28 cons: SEQUENCE
  217:d=7  hl=2 l=   9 prim: OBJECT            :signingTime
  228:d=7  hl=2 l=  15 cons: SET
  230:d=8  hl=2 l=  13 prim: UTCTIME           :141124081613Z
  245:d=6  hl=2 l=  35 cons: SEQUENCE
  247:d=7  hl=2 l=   9 prim: OBJECT            :messageDigest
  258:d=7  hl=2 l=  22 cons: SET
  260:d=8  hl=2 l=  20 prim: OCTET STRING      [HEX DUMP]:221DF0EEC7FB07752C2360E9988D354E9366D26A
  282:d=5  hl=2 l=   9 cons: SEQUENCE
  284:d=6  hl=2 l=   7 prim: OBJECT            :dsaWithSHA1
  293:d=5  hl=2 l=  47 prim: OCTET STRING      [HEX DUMP]:302D02147A10B413FBCB9E9253668B30AB4A3BC6F2F5530302150090A2E63B96104049787D86507E0AB40F2C46B20A

There I see the message digest which is a sha1 hash value of the original message. The original message is ($message in PHP below):

W1005056A57D331ED49CF644B265BC8C33datarcudcCN%3DSE2,OU%3DI0020184890,OU%3DSAPWebAS,O%3DSAPTrustCommunity,C%3DDE20141124101613

The sha1 value of this message is:

221df0eec7fb07752c2360e9988d354e9366d26a

which is the same as the message digest in the ASN.1 structure. There is a second hash value with dsaWithSHA1. I don't know, how to generate the hash with this algorithm.

When I try to verify it via PHP:

openssl_verify($message, $secKeyDer, $pubKey, 'sha1');

I am getting the error:

error:0906D06C:PEM routines:PEM_read_bio:no start line
error:0606C06E:digital envelope routines:EVP_VerifyFinal:wrong public key type

This irritates me because $pubKey's value is in PEM format as described in the function's manual.

My question is now: How can I verify the message in PHP with the given parameters (original message, signed message (seckey.der), public key). Or alternatively with native OpenSSL commands.

Regards, Chris.

2

There are 2 answers

1
Chris On

Now I found the answer with OpenSSL:

openssl cms -verify -in seckey.der -inform der -content message.txt -noverify -certfile certificate.cer

where seckey.der is the signature in DER format, message.txt is the original message and certificate.cer is the public key in PEM format.

0
Tilo On

old Q, but same as @FrankStein it took me a bit to figure out what the message was/is but here a bash and openSSL cmd to verify the signature along with some detail where the message is from:

####bash style check with openssl

##secKey directly from URL (well URL decode)
secKeyBase64='MIIBUQYJKoZIhvcN--removed a few chars--YEFF/iMK2ISP+vS5evTe--removed--UZ3vcpINI='

###all parameters from URL without pVersion and secKey. keep the order from URL!
message='Z3
002248AF19E21EEEB782F2D94A9D2B17
r
CN%3DID3,OU%3DI0120003411,OU%3DSAPWebAS,O%3DSAPTrustCommunity,C%3DDE
20240307021358'

#base64 decode and write seckey to file
base64 -d <<< $secKeyBase64 > sap-sec-key.p7b

#write message to file
tr -d '[:space:]' <<< $message > message.txt

##info about the secKey
openssl asn1parse -in sap-sec-key.p7b -inform der
##convert SAP cert to PEM format (as openssl want this)
openssl pkcs7 -inform der  -print_certs -in Z3.cer -out Z3.pem
#now check signature for the message
openssl cms -verify -in sap-sec-key.p7b -inform der -content message.txt -noverify -certfile Z3.pem

##Output
Z3002248AF19E21EEEB782F2D94A9D2B17rCN%3DID3,OU%3DI0120003411,OU%3DSAPWebAS,O%3DSAPTrustCommunity,C%3DDE20240307021358CMS Verification successful