So i am fiddling with this website's IPN function to see if i wan't to incorporate it to some dumb project my friends and i are working on. To be honest i don't know much C# in depth, i'm fairly new to the language (a few months of coding practice).
This is the PHP sample they give out on how to use it:
https://github.com/Rocketr/rocketrnet-ipn-php/blob/master/example_rocketr_ipn.php
I am trying to make a receiver like that in MVC 5. I have the Model setup with a function when the IPN hits the server page to process the request but it seems to just fail out everytime and not write any raw data i am trying to capture to the logs.
// GET: Purchases/Incoming
public void Incoming()
{
var ipnDebugLog = HttpRuntime.AppDomainAppPath + "/Logs/IPN/debug.txt";
var testIPNKey = "the hash here";
byte[] ipnToByes = Encoding.ASCII.GetBytes(testIPNKey); // IPN string to byteto hash with
var recvdIPN = Request["HTTP_IPN_HASH"];
HMACSHA256 testHash = new HMACSHA256(ipnToByes); // Setting testHash to IPN secret string
string ipnHeader = Request["IPN_HASH"];
using (StreamWriter sw = new StreamWriter(ipnDebugLog))
{
sw.WriteLine(ipnHeader);
foreach (var reqHead in ipnHeader)
{
sw.WriteLine(reqHead.ToString());
sw.WriteLine("JSON String: " + Request["HTTP_IPN_SECRET"]);
sw.WriteLine(recvdIPN);
sw.WriteLine("From: " + GetIPAddress());
}
}
}
So this is just me trying to get the data being sent from Rocketr. On the site it states:
To verify the integrity of the payload, we will send an HMAC signature
over a HTTP header called “IPN_HASH”. The HMAC signature will be a
signed json encoded POST object with your IPN secret. You can see how
to verify the signature in the example_rocketr_ipn.php file in this
repository.
Am i just to dumb and new to understand C# to function like this? I feel like i'm on the right track to reading the raw data but i'm probly wrong?
So to sum up the question
Am i doing the incorrect way to read a raw custom HTTP header called IPN_HASH? Going off of the PHP example they used isset to read a server variable header labled HTTP_IPN_HASH right?
So i have to convert this $hmac = hash_hmac("sha512", json_encode($_POST), trim($IPN_SECRET));
Try this (make adjustments as needed/necessary):
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
namespace Foo
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void PhpHashTest()
{
string IPN_SECRET = "I-am-the-secret";
//Mocking some HTTP POSTed data
var someFormUrlEncodedData = "order_id=1234&product_title=Hello%20World&product_id=Sku123";
//Mocking json_encode($_POST)
var data = HttpUtility.ParseQueryString(someFormUrlEncodedData);
var dictionary = data.AllKeys.ToDictionary(key => key, key => data[key]);
//{"order_id":"1234","product_title":"Hello World","product_id":"Sku123"}
var json = JsonConvert.SerializeObject(dictionary);
byte[] bytes;
using (var hmac512 = new HMACSHA512(Encoding.ASCII.GetBytes(IPN_SECRET)))
{
bytes = hmac512.ComputeHash(Encoding.ASCII.GetBytes(json));
}
//will contain lower-case hex like Php hash_hmac
var hash = new StringBuilder();
Array.ForEach(bytes, b => hash.Append(b.ToString("x2")));
//Assert that Php output exactly matches implementation
Assert.IsTrue(string.Equals("340c0049bde54aa0d34ea180f8e015c96edfc4d4a6cbd7f139d80df9669237c3d564f10366f3549a61871779c2a20d2512c364ee56af18a25f70b89bd8b07421", hash.ToString(), StringComparison.Ordinal));
Console.WriteLine(hash);
}
}
}
Not a PHP dev - this is my "Php version":
<?php
$IPN_SECRET = 'I-am-the-secret';
# 'order_id=1234&product_title=Hello%20World&product_id=Sku123';
$json = array('order_id' => '1234', 'product_title' => 'Hello World', 'product_id' =>'Sku123');
echo json_encode($json);
echo "<br />";
$hmac = hash_hmac("sha512", json_encode($json), trim($IPN_SECRET));
echo $hmac;
?>
Hth....
Related
I can't get the signature verification working, like it's described here. I'm using BouncyCastle.NetCore 1.8.1.3 and the project is a .NETCoreApp 1.0.
I'm developing on macOS 10.12.1, running dotnet core 1.0.4 and my server is running Ubuntu 16.04.2-x64 running the release version, build as netcore1.0 and ubuntu16.04-x64 app.
The rest of the system runs without problems, except the signature verification.
My validation always returns false.
Here is my service for validating the signature and body:
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
namespace MySkill.Main.Services
{
public class CertificationValidationService : ICertificationValidationService
{
private const string Algorithm = "SHA1withRSA";
public async Task<bool> IsValidSiganture(Stream body, Stream certData, string signature)
{
var pemReader = new Org.BouncyCastle.OpenSsl.PemReader(new StreamReader(certData));
var cert = (Org.BouncyCastle.X509.X509Certificate)pemReader.ReadObject();
using (var sr = new StreamReader(body))
{
var content = await sr.ReadToEndAsync();
var result = CheckRequestSignature(Encoding.UTF8.GetBytes(content), signature, cert);
return result;
}
}
private static bool CheckRequestSignature(byte[] bodyData, string signature, Org.BouncyCastle.X509.X509Certificate cert)
{
byte[] sig = Convert.FromBase64String(signature);
var pubKey = (Org.BouncyCastle.Crypto.Parameters.RsaKeyParameters)cert.GetPublicKey();
var signer = Org.BouncyCastle.Security.SignerUtilities.GetSigner(Algorithm);
signer.Init(false, pubKey);
signer.BlockUpdate(bodyData, 0, bodyData.Length);
return signer.VerifySignature(sig);
}
}
}
Does anybody have a tip, what i'm doing wrong or has used a different framework or apis?
From the code you shared it looks correct. Without seeing the rest of the code I am not sure if the Signature you got is correct. You can take a look at our C# code that passed certification at https://github.com/sophtron/Alexa-Skill-Sophtron and compare against your own to see if there are any differences.
I tried RSACryptoServiceProvider from .net library for signature validation and it had never worked. So I had to switch to BouncyCastle.1.8.1 too and it worked for me.
I've got a AllegroGraph server running and have trouble querying remote datastore, there's very little information on documentation.
Here's my lil piece of code:
using System;
using VDS.RDF;
using VDS.RDF.Storage;
namespace PoC {
class Program {
static void Main(string[] args) {
string server = "http://server";
string repo = "repo";
string username = "username";
string password = "password";
AllegroGraphConnector agraph = new AllegroGraphConnector(server, repo, username, password);
Options.HttpDebugging = true;
Options.HttpFullDebugging = true;
agraph.Query("SELECT * WHERE { emid:_PCAT_0001 ?p ?o }");
Console.ReadLine();
}
}
}
MALFORMED QUERY: Parse error: namespace mapping for "emid" not defined
when expanding QName "emid:_PCAT_0001".
Although in AllegroGraph WebView I can run exactly the same query and namespace is loaded into repository.
How do I resolve that?
You will need to declare the prefix emid: in your query. Presumably the AllegroGraph WebView UI is doing that automatically for you, but the plain SPARQL endpoint won't.
Try using something like this:
agraph.Query("PREFIX emid: <http://your.uri.goes/here> SELECT * WHERE { emid:_PCAT_0001 ?p ?o }");
Obviously you should replace that fake URI with the real URI that your emid: prefix maps to!
We need to work on .net based web application that will upload files to Amazon S3 Storage bucket using admin panel of the app and clients will be given to downloadable files with client.aspx file.
We looked at few example and got confused with some of the sample code for downloading non public files from S3 storage. one such example is below
AmazonS3Config config = new AmazonS3Config()
{
RegionEndpoint = RegionEndpoint.USEast1
};
IAmazonS3 client = new AmazonS3Client(accessKey, secretKey, config);
string dest = System.IO.Path.GetTempPath() + "event.mp4";
using (client)
{
GetObjectRequest request = new GetObjectRequest() { BucketName = "bucketname" + #"/" + "videos2015", Key = "event.mp4" };
using (GetObjectResponse response = client.GetObject(request))
{
response.WriteResponseStreamToFile(dest);
}
}
Response.Clear();
Response.AppendHeader("content-disposition", "attachment; filename=" + "dynamic_filename.png");
Response.ContentType = "application/octet-stream";
Response.TransmitFile(dest);
Response.Flush();
Response.End();
When user click on the link following code gets executed on web server and code downloads file on the web server and then serves the same file to client... if i am not wrong. Is there not a way that we can serve file for download directly from the AWS S3 storage.
In above case it is waste of server resources and increases the download time also.
Out files on AWS are not Public they are non public so the url is not accessible directly from client browsers as is in case of public content type
The pre-signed urls are indeed what you are looking for. Since you are using C#, here is a link to some useful code examples:
http://docs.aws.amazon.com/AmazonS3/latest/dev/ShareObjectPreSignedURLDotNetSDK.html
There is no need to upload files to s3 thru your webserver, they can be sent directly. Same thing on the download, download directly from S3 - don't copy them to EC2 first, you would be wasting bandwidth and processing resources.
You can use Minio-dotnet client library Its Open Source & supports compatible S3 API.
Here is an example for PresignedPostPolicy
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Minio;
namespace Minio.Examples
{
class PresignedPostPolicy
{
static int Main()
{
/// Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY, my-bucketname and
/// my-objectname are dummy values, please replace them with original values.
var client = new MinioClient("s3.amazonaws.com", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY");
PostPolicy form = new PostPolicy();
DateTime expiration = DateTime.UtcNow;
form.SetExpires(expiration.AddDays(10));
form.SetKey("my-objectname");
form.SetBucket("my-bucketname");
Dictionary <string, string> formData = client.PresignedPostPolicy(form);
string curlCommand = "curl ";
foreach (KeyValuePair<string, string> pair in formData)
{
curlCommand = curlCommand + " -F " + pair.Key + "=" + pair.Value;
}
curlCommand = curlCommand + " -F file=#/etc/bashrc https://s3.amazonaws.com/my-bucketname";
Console.Out.WriteLine(curlCommand);
return 0;
}
}
}
And below one for PresignedPutObject
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Minio;
namespace Minio.Examples
{
class PresignedPutObject
{
static int Main()
{
/// Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY, my-bucketname and
/// my-objectname are dummy values, please replace them with original values.
var client = new MinioClient("s3.amazonaws.com", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY");
Console.Out.WriteLine(client.PresignedPutObject("my-bucketname", "my-objectname", 1000));
return 0;
}
}
}
Hope it helps.
PS: I work for Minio
I am looking for a simple example of accessing the Amazon Mechanical Turk web service in C#. I know there is a SDK for C# but I want to understand the basic mechanics before using that.
Here is the simplest code example I've come up with to access Mechanical Turk. It creates the signature and calls the GetAccountBalance operation.
using System;
using System.Globalization;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;
namespace TurkTest {
class Program {
static void Main(string[] args) {
const string SERVICE_NAME = "AWSMechanicalTurkRequester"; // requester service for MTurk
const string TIMESTAMP_FORMAT = "yyyy-MM-ddTHH:mm:ss.fffZ";
// Modify these with your values.
const string operation = "GetAccountBalance";
const string accessKey = "<Your access key>";
const string secretAccessKey = "<Your secret access key>";
// Millisecond values in the timestamp string can result in intermittent BadClaimsSupplied errors.
// Get the current UTC time and use that to create a new time with milliseconds set to zero to avoid this case.
DateTime now = DateTime.UtcNow;
now = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, 0, DateTimeKind.Utc);
string timeStamp = now.ToString(TIMESTAMP_FORMAT, CultureInfo.InvariantCulture);
// Create the hash-based messaged authentication algorithm (SHA1) using our secret access key as the key.
var hmac = new HMACSHA1(Encoding.UTF8.GetBytes(secretAccessKey));
// Combine the service name, operation and timestamp and then hash them to produce the signature.
var dataBytes = Encoding.UTF8.GetBytes(SERVICE_NAME + operation + timeStamp);
string signature = Convert.ToBase64String(hmac.ComputeHash(dataBytes));
// Build the URL to send to Amazon
string url =
#"https://mechanicalturk.amazonaws.com/?Service=AWSMechanicalTurkRequester&AWSAccessKeyId={0}&Version=2012-03-25&Operation={1}&Signature={2}&Timestamp={3}";
url = string.Format(url, accessKey, operation, signature, timeStamp);
// Send a request and write the response to the console.
using (WebClient client = new WebClient()) {
using (StreamReader reader = new StreamReader(client.OpenRead(url))) {
Console.WriteLine(reader.ReadToEnd());
}
}
Console.Read();
}
}
}
before writing my own :-)
I was wondering if anyone knows a tool to parse a URL and extract all the params into a easier viewable format, a grid maybe? (these urls are extremely long :- )
And also if it allows you to construct the querystring for standard text and automates the URL ENCODING etc.
Must be one available, i have searched high and low and can't find anything.
Thanks in advance
The ParseQueryString method is pretty handy for those tasks.
I was wondering if anyone knows a tool to parse a URL and extract all
the params into a easier viewable format, a grid maybe? (these urls
are extremely long :- )
using System;
using System.Web;
class Program
{
static void Main()
{
var uri = new Uri("http://foo.com/?param1=value1¶m2=value2");
var values = HttpUtility.ParseQueryString(uri.Query);
foreach (string key in values.Keys)
{
Console.WriteLine("key: {0}, value: {1}", key, values[key]);
}
}
}
And also if it allows you to construct the querystring for standard
text and automates the URL ENCODING etc.
using System;
using System.Web;
class Program
{
static void Main()
{
var values = HttpUtility.ParseQueryString(string.Empty);
values["param1"] = "value1";
values["param2"] = "value2";
var builder = new UriBuilder("http://foo.com");
builder.Query = values.ToString();
var url = builder.ToString();
Console.WriteLine(url);
}
}