4

OpenSSL newbie here.

We're using OpenSSL to parse and verify the certificate and signature that Amazon's Alexa sends to external web services, following their list of requirements in the instructions here.

We're successfully extracting the public key, checking the start/end dates of the certificate, verifying that echo-api.amazon.com is the subject of the certificate, and verifying the chain of trust (by using OpenSSL command line functions).

But we're stuck at the point where the Amazon documentation says to "Use the public key extracted from the signing certificate to decrypt the encrypted signature to produce the asserted hash value."

Is this possible with OpenSSL? The openssl "rsautl -decrypt" command is only for private keys (both the documentation and our tests confirm this, and public keys are rejected, even with the -pubin option).

Alternately, is there a way to get the openssl dgst -verify to work for the Alexa signature verification?

We're testing these commands:

openssl base64 -d -in (signature_file) -out /tmp/sign.sha256 
openssl dgst -sha256 -verify (pub-key_file) -signature /tmp/sign.sha256 (file)

We've used ColdFusion's getHttpRequestData().headers["Signature"] function to get the signature:

lOtMJdnw8fffdJHkiM2I6m+K0IqkMCeAWJrjoYGVtkGEBYXUOUazKh6/rpM6opxni7YMHJkA6x5/eGGmWg++VP
0+2I/TNQjR9TTu1LVKikGyi9Oskk/od/tKzEhyWJ2noyyrybqRG1bTSLjVqc1RxDLLRbDuOs12s5F6E0bL18pG
EAww6iMKr2m212wrVzJ2pehp8wVMcqlegOaXW2iFlAunWwte7E/br4vdsYiAXZRLg2uVBDvjmpeo4b9GJZbZkE
HhV+/x+KOwXCISl+Ao0BTr/pzfuF4m/oWpX1PC91hwYMSiVn9I+a+VDxKVxSVllCrffIAIc9mETVuc9U0XRA==

And the Coldfusion GetHttpRequestData().content function returns the JSON structure sent to the web service:

{  
   "version":"1.0",
   "session":{  
      "new":true,
      "sessionId":"SessionId.29d1522f-6ea6-4aba-b782-f41890388569",
      "application":{  
         "applicationId":"amzn1.ask.skill.63fd6ac5-ed2b-4324-995c-681f96f428a6"
      },
      "attributes":{  

      },
      "user":{  
         "userId":"amzn1.ask.account.AHURACZZDQ43ZMUVTOQBEGB5JMWOZCFJRFYXCO26O2IZ3JRS6HYKBOOXPEM6BNWLPUM2E6EWCDC4Q2DPFHXSE3EJT4BLL4CWDNDIFASIHIV2D4AJDH7MDICIFVMHK252EBVQOGFR2TH4HNGMMTPOHI5VGQD7O4UWPZOL2FQOGRCNMVUPUI3SC2R2EH5L5V6XD7B7IF544TYJJCA"
      }
   },
   "request":{  
      "type":"IntentRequest",
      "requestId":"EdwRequestId.d8e9d467-b311-4d9c-8273-9ba0b1e07613",
      "timestamp":"2017-05-11T18:49:37Z",
      "locale":"en-US",
      "intent":{  
         "name":"GetRssFeedHeadlines",
         "slots":{  
            "RSSFeedLabel":{  
               "name":"RSSFeedLabel",
               "value":"top news"
            }
         }
      }
   }
}

Here's the public key:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnK+zBruRA1TnbgQGxE+b
4XiTTZyDkGwJ6068AGsXQmgt9lVhC8CTTC4wdR5NXosboV6/63worQCNo412csBV
jUy3H1/VEs+5Kv+AiAOUuKoBfEU8zAvHCc7GmOKUgNidcDA0MSpx3ZTMSGGbkfaL
ikRzne6nFZ6jNOnkqTtGD6SrCIYgLNArScYoPzIcXEypHFrognzrR4Ee0YcefGZy
S81Yqev/lli01dAgRvpnAty68rYTmxkNhzUSG6IIbFHIxXJKAETAkGiKJcgZpfG2
1Ok5Dk3yGrESY/ID5OnxvMxiXSnXwht8JD6bd15ui0tPDa85B0jpZLloqQZe26oR
owIDAQAB
-----END PUBLIC KEY-----

But the openssl dgst always returns a message of "Verification Failed" when we use the openssl dgst -verify with files containing the signature (trying raw and Base64-decoded) and http request body (listed above).

Any guidance would be much appreciated!

4

First, Amazon and you are repeating a common but wrong trope; signature is not encryption with the private key -- not even for RSA, where there is enough similarity in the mathematical underpinning that it is dangerously appealing to think this even though there are vital differences in the actual schemes and trying to interchange them leads to very bad results, and totally completely not at all for other algorithms like DSA and ECDSA. See:
Trying to understand RSA and it's terminology?
Is encrypting data with a private key dangerous?
If the public key can't be used for decrypting something encrypted by the private key, then how do digital signatures work?
Understanding digitial certifications
Digital Signature and Verification?
With GPG, can you "decrypt" a file that hasn’t been encrypted?
Why should I sign data that's already encrypted?
Is encrypting data with a private key dangerous?
Does RSA encryption always pad small amounts of data to some larger size?
https://crypto.stackexchange.com/questions/15997/is-rsa-encryption-the-same-as-signature-
https://crypto.stackexchange.com/questions/13107/symmetric-encryption-is-no-longer-necessary
https://crypto.stackexchange.com/questions/2123/rsa-encryption-with-private-key-and-decryption-with-a-public-key
(some of which I admit are hard to find unless you know what you are looking for).

That said, openssl rsautl can recover the signed padded hash from a signature using the -verify option, and the newer pkeyutl with (clearer) -verifyrecover; given your de-base64-ed signature in temp.sig and your publickey in temp.key:

$ openssl rsautl -verify -pubin -inkey temp.key <temp.sig |openssl asn1parse -inform der
    0:d=0  hl=2 l=  33 cons: SEQUENCE
    2:d=1  hl=2 l=   9 cons: SEQUENCE
    4:d=2  hl=2 l=   5 prim: OBJECT            :sha1
   11:d=2  hl=2 l=   0 prim: NULL
   13:d=1  hl=2 l=  20 prim: OCTET STRING      [HEX DUMP]:AE2F2DD493F3E58F62E9F20678D9A05B86E06F8A

Observe this is a SHA-1 hash, as stated on the Amazon page you link, not SHA-256, and does match the SHA-1 hash of your data:

 $ openssl sha1 <temp.dat
 (stdin)= ae2f2dd493f3e58f62e9f20678d9a05b86e06f8a

and thus can be verified with dgst -verify

 $ openssl sha1 <temp.dat -verify temp.key -signature temp.sig
 Verified OK

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.