Hi All,
I would like to use Amazon Alexa Web Information Service API in my application but they are not providing c# code to create asignature. They are provided sample codes in Java, PHP, etc. We would like to use this API in c# only. So, I tried to convert java code to c# but not succeded. Searched for online conversion tools but not found suffient solution. Here I am providing Java and my c# code. Can anyone help me on this, how to convert java to c#
Java:
import sun.misc.BASE64Encoder;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.security.SignatureException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* Makes a request to the Alexa Web Information Service UrlInfo action.
*/
public class UrlInfo {
private static final String ACTION_NAME = "UrlInfo";
private static final String RESPONSE_GROUP_NAME = "Rank,ContactInfo,LinksInCount";
private static final String SERVICE_HOST = "awis.amazonaws.com";
private static final String AWS_BASE_URL = "http://" + SERVICE_HOST + "/?";
private static final String HASH_ALGORITHM = "HmacSHA256";
private static final String DATEFORMAT_AWS = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
private String accessKeyId;
private String secretAccessKey;
private String site;
public UrlInfo(String accessKeyId, String secretAccessKey, String site) {
this.accessKeyId = accessKeyId;
this.secretAccessKey = secretAccessKey;
this.site = site;
}
/**
* Generates a timestamp for use with AWS request signing
*
* @param date current date
* @return timestamp
*/
protected static String getTimestampFromLocalTime(Date date) {
SimpleDateFormat format = new SimpleDateFormat(DATEFORMAT_AWS);
format.setTimeZone(TimeZone.getTimeZone("GMT"));
return format.format(date);
}
/**
* Computes RFC 2104-compliant HMAC signature.
*
* @param data The data to be signed.
* @return The base64-encoded RFC 2104-compliant HMAC signature.
* @throws java.security.SignatureException
* when signature generation fails
*/
protected String generateSignature(String data)
throws java.security.SignatureException {
String result;
try {
// get a hash key from the raw key bytes
SecretKeySpec signingKey = new SecretKeySpec(
secretAccessKey.getBytes(), HASH_ALGORITHM);
// get a hasher instance and initialize with the signing key
Mac mac = Mac.getInstance(HASH_ALGORITHM);
mac.init(signingKey);
// compute the hmac on input data bytes
byte[] rawHmac = mac.doFinal(data.getBytes());
// base64-encode the hmac
// result = Encoding.EncodeBase64(rawHmac);
result = new BASE64Encoder().encode(rawHmac);
} catch (Exception e) {
throw new SignatureException("Failed to generate HMAC : "
+ e.getMessage());
}
return result;
}
/**
* Makes a request to the specified Url and return the results as a String
*
* @param requestUrl url to make request to
* @return the XML document as a String
* @throws IOException
*/
public static String makeRequest(String requestUrl) throws IOException {
URL url = new URL(requestUrl);
URLConnection conn = url.openConnection();
InputStream in = conn.getInputStream();
// Read the response
StringBuffer sb = new StringBuffer();
int c;
int lastChar = 0;
while ((c = in.read()) != -1) {
if (c == '<' && (lastChar == '>'))
sb.append('\n');
sb.append((char) c);
lastChar = c;
}
in.close();
return sb.toString();
}
/**
* Builds the query string
*/
protected String buildQuery()
throws UnsupportedEncodingException {
String timestamp = getTimestampFromLocalTime(Calendar.getInstance().getTime());
Map<String, String> queryParams = new TreeMap<String, String>();
queryParams.put("Action", ACTION_NAME);
queryParams.put("ResponseGroup", RESPONSE_GROUP_NAME);
queryParams.put("AWSAccessKeyId", accessKeyId);
queryParams.put("Timestamp", timestamp);
queryParams.put("Url", site);
queryParams.put("SignatureVersion", "2");
queryParams.put("SignatureMethod", HASH_ALGORITHM);
String query = "";
boolean first = true;
for (String name : queryParams.keySet()) {
if (first)
first = false;
else
query += "&";
query += name + "=" + URLEncoder.encode(queryParams.get(name), "UTF-8");
}
return query;
}
/**
* Makes a request to the Alexa Web Information Service UrlInfo action
*/
public static void main(String[] args) throws Exception {
if (args.length < 3) {
System.err.println("Usage: UrlInfo ACCESS_KEY_ID " +
"SECRET_ACCESS_KEY site");
System.exit(-1);
}
// Read command line parameters
String accessKey = args[0];
String secretKey = args[1];
String site = args[2];
UrlInfo urlInfo = new UrlInfo(accessKey, secretKey, site);
String query = urlInfo.buildQuery();
String toSign = "GET\n" + SERVICE_HOST + "\n/\n" + query;
System.out.println("String to sign:\n" + toSign + "\n");
String signature = urlInfo.generateSignature(toSign);
String uri = AWS_BASE_URL + query + "&Signature=" +
URLEncoder.encode(signature, "UTF-8");
System.out.println("Making request to:\n");
System.out.println(uri + "\n");
// Make the Request
String xmlResponse = makeRequest(uri);
// Print out the XML Response
System.out.println("Response:\n");
System.out.println(xmlResponse);
}
}
My C# Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Web;
using System.Xml;
using HtmlAgilityPack;
namespace SampleConsoleWebCrawler
{
class Program
{
private const string ACTION_NAME = "UrlInfo";
private const string RESPONSE_GROUP_NAME = "Rank,ContactInfo,LinksInCount";
private const string SERVICE_HOST = "awis.amazonaws.com";
private static readonly string AWS_BASE_URL = "http://" + SERVICE_HOST + "/?";
private const string HASH_ALGORITHM = "HmacSHA1";
private const string DATEFORMAT_AWS = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
public static readonly string APIKey = "xyz";
public static readonly string SecKey = "xyz";
public static readonly string Site = "yahoo.com";
static void Main(string[] args)
{
string mainquery = buildQuery();
string toSign = "GET\n" + SERVICE_HOST + "\n/\n" + mainquery;
Console.WriteLine("String to sign:\n" + toSign + "\n");
string signature = generateSignature(toSign);
string uri = AWS_BASE_URL + mainquery + "&Signature=" + Encode(signature);
//will pass this url to webrequest
}
protected static string getTimestampFromLocalTime(DateTime date)
{
string timestamp = DateTime.UtcNow.ToString("s", System.Globalization.CultureInfo.InvariantCulture);
return timestamp;
}
protected static string generateSignature(string data)
{
string result;
try
{
HMACSHA1 hmacsha1 = new HMACSHA1();
byte[] secretKeyBArr = Encoding.UTF8.GetBytes(SecKey);
byte[] contentBArr = Encoding.UTF8.GetBytes(data);
hmacsha1.Key = secretKeyBArr;
byte[] final = hmacsha1.ComputeHash(contentBArr);
result = Convert.ToBase64String(final);
return result;
}
catch (Exception e)
{
//throw new SignatureException("Failed to generate HMAC : " + e.Message);
return "";
}
}
protected static string buildQuery()
{
string timestamp = getTimestampFromLocalTime(new DateTime());
IDictionary<string, string> queryParams = new SortedDictionary<string, string>();
queryParams["Action"] = ACTION_NAME;
queryParams["ResponseGroup"] = RESPONSE_GROUP_NAME;
queryParams["AWSAccessKeyId"] = APIKey;
queryParams["Timestamp"] = timestamp;
queryParams["Url"] = Site;
queryParams["SignatureVersion"] = "2";
queryParams["SignatureMethod"] = HASH_ALGORITHM;
string query = "";
bool first = true;
foreach (string name in queryParams.Keys)
{
if (first)
{
first = false;
}
else
{
query += "&";
}
query += name + "=" + Encode(queryParams[name]);
}
return query;
}
private static string Encode(string toEncode)
{
byte[] toEncodeAsBytes = System.Text.Encoding.UTF8.GetBytes(toEncode);
string returnValue = System.Convert.ToBase64String(toEncodeAsBytes);
return returnValue;
}
}
}