This is a bit of a cross post with stackoverflow, no flaming pls.
I’ve written an Alexa Skill in PowerShell, but it got rejected because I’m not validating a signature properly.
Instructions are here: Host a Custom Skill as a Web Service | Alexa Skills Kit
I’m good up to:
6.- Use the public key extracted from the signing certificate to decrypt the encrypted signature to produce the asserted hash value.
7.- Generate a SHA-1 hash value from the full HTTPS request body to produce the derived hash value
8.- Compare the asserted hash value and derived hash values to ensure that they match.
#certUrl = https://s3.amazonaws.com/echo.api/echo-api-cert-4.pem
$cert = Get-PfxCertificate -FilePath $dlPath
# 5.- Base64-decode the Signature header value on the request to obtain the encrypted signature
$encryptedSignatureBytes = [System.Convert]::FromBase64String($Json.signature)
# 6.- Use the public key extracted from the signing certificate to decrypt the encrypted signature to produce the asserted hash value
$publicKey = $cert.GetPublicKey() #returns long System.Byte
$assertedHash = $cert.PublicKey.Key.Decrypt($encryptedSignatureBytes, $false) #Exception calling "Decrypt" with "2" argument(s): "Key does not exist.
# 7.- Generate a SHA-1 hash value from the full HTTPS request body to produce the derived hash value
$requestBodySHA1 = $(Get-StringHash $Json.requestBody)
# 8.- Compare the asserted hash value and derived hash values to ensure that they match
if($assertedHash -eq $requestBodySHA1)
{
#process
}
I’ve tried using $cert.PublicKey.Key.VerifyHash, $cert.PublicKey.Key.VerifyData, $cert.PublicKey.Key.signHash, $cert.PublicKey.Key.SignData, but I’m lost.
@Andrew thanks for your interest.
I ended up figuring out the issue once I understood the actual requirement. In order to compare the signature and Amazon post request, all I had to do was get the request as a Byte the Signature was already Byte from Base64 conversion, then feed it in to the function $cert.PublicKey.Key.VerifyData
If I change any byte in either the Signature or Request it fails.
Previously I was hashing the request JSON and trying to compare to whatever I could get from the public key, which was wrong.
# 7.- Generate a SHA-1 hash value from the full HTTPS request body to produce the derived hash value
$requestBodyBytes = [System.IO.File]::ReadAllBytes($req)
# 8.- Compare the asserted hash value and derived hash values to ensure that they match
$sha1Oid = [System.Security.Cryptography.CryptoConfig]::MapNameToOID('SHA1')
if(!($cert.PublicKey.Key.VerifyData($requestBodyBytes, $sha1Oid, $encryptedSignatureBytes)))
{
$validErr += "`nFailed request hash comparison to signature."
}
I’d be really interested to see your end product and how you’re hosting it once you’re done, as I’ve got a project on the go I’d love to add an Alexa skill to.