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;
 }
 }
 
}