1

I am trying to generate voice files with the Ivona tts service. However I have tried to follow there authentication steps to the tee and can't seem to successfully authenticate. Here is the script I am running.

require 'uri'
require 'openssl'
require 'net/http'
require 'cgi'

method = 'POST'
service_string = 'tts'
host = 'tts.eu-west-1.ivonacloud.com'
region = 'eu-west-1'
canonical_uri = 'CreateSpeech'
endpoint = "https://tts.eu-west-1.ivonacloud.com/#{canonical_uri}"

t = Time.now.utc
amzdate = t.strftime('%Y%m%dT%H%M%SZ')
datestamp = t.strftime('%Y%m%d')
query = "'Hello_world'"

def getSignatureKey(key, dateStamp, regionName, serviceName)
  kDate    = OpenSSL::HMAC.digest('sha256', "AWS4" + key, dateStamp)
  kRegion  = OpenSSL::HMAC.digest('sha256', kDate, regionName)
  kService = OpenSSL::HMAC.digest('sha256', kRegion, serviceName)
  kSigning = OpenSSL::HMAC.digest('sha256', kService, "aws4_request")
  kSigning
end

access_key = "access_key_goes_here"
secret_key = "secret_goes_here"

# Task 1: Create a Canonical Request For Signature Version 4
# http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
signed_headers = 'content-type;host;x-amz-content-sha256;x-amz-date'
payload_hash = OpenSSL::Digest.new("sha256").hexdigest("{'Input':{'Data':#{query}}}")
canonical_headers = ['content-type:application/json',
                     'host:' + host, "x-amz-content-sha256:#{payload_hash}",
                     'x-amz-date:' + amzdate].join("\n") + "\n"

canonical_request = [method, canonical_uri, canonical_headers,
                     signed_headers, payload_hash].join("\n")


# Task 2: Create a String to Sign for Signature Version 4
# http://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html
algorithm = 'AWS4-HMAC-SHA256'
credential_scope = [datestamp, region, service_string, 'aws4_request'].join("/")
string_to_sign = [
  algorithm, amzdate, credential_scope,
  OpenSSL::Digest.new("sha256").hexdigest(canonical_request)
].join("\n")


# Task 3: Calculate the AWS Signature Version 4
# http://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html
signing_key = getSignatureKey(secret_key, datestamp, region, service_string)


# Task 4: Add the Signing Information to the Request
# http://docs.aws.amazon.com/general/latest/gr/sigv4-add-signature-to-request.html

signature = OpenSSL::HMAC.hexdigest('sha256', signing_key, string_to_sign)

puts signature

uri = URI.parse(endpoint)
https = Net::HTTP.new(uri.host,uri.port)
https.use_ssl = true
https.set_debug_output($stdout)
request = Net::HTTP::Post.new(uri.request_uri)
request.body = "{'Input':{'Data':#{query}}}"
auth = "#{algorithm} Credential=#{access_key + '/' + credential_scope}, SignedHeaders=#{signed_headers}, Signature=#{signature}"

request.add_field 'Content-Type', "application/json"
request.add_field 'X-Amz-Date', amzdate
request.add_field 'X-Amz-Content-Sha256', payload_hash
request.add_field 'Authorization', auth
request.add_field 'Content-Length', "32"

https.request(request)
villy393
  • 2,985
  • 20
  • 28
  • What's the error you receive? Have you tried your code against the [Signature Version 4 Test Suite](http://docs.aws.amazon.com/general/latest/gr/signature-v4-test-suite.html)? – Michael - sqlbot Apr 10 '16 at 17:49
  • 1
    I get a 403 - Authentication failed. I tried the test suite but didn't really know how to work it. – villy393 Apr 10 '16 at 18:12
  • The test suite is intended to be used with the test credentials (listed on the linked page). It contains requests that you are supposed to sign with your code, to verify that you get the same result they list. The zip file contains the requests, the correct solutions, and the intermediate results from the signing process, all in individual files. – Michael - sqlbot Apr 11 '16 at 00:54

0 Answers0