I have an outgoing POST from another application, and with the help of Fiddler I want to send another order opening request. I managed to take the necessary data from the original request, sign the request using HMAC256 and send it to Binance, but I get a "bad request" in the response and I don't understand what's wrong here. I would appreciate any help.
public static void OnBeforeResponse(Session oSession)
{
if (oSession.HTTPMethodIs("POST") && oSession.uriContains("order"))
{
String strBody = oSession.GetRequestBodyAsString();
//Price
int PriceStart = strBody.IndexOf("price=") + 6;
int PriceEND = strBody.IndexOf("&", PriceStart);
string priceStr = strBody.Substring(PriceStart, PriceEND - PriceStart);
float priceF = float.Parse(priceStr, System.Globalization.CultureInfo.InvariantCulture);
// SYMBOL
int symbolStart = strBody.IndexOf("symbol=") + 7;
int symbolend = strBody.IndexOf("BTC", symbolStart);
string symbol = strBody.Substring(symbolStart, symbolend - symbolStart);
// Quantity
int quantStart = strBody.IndexOf("quantity=") + 9;
int quantend = strBody.IndexOf("&price", quantStart);
string quant = strBody.Substring(quantStart, quantend - quantStart);
float quantity = float.Parse(quant, System.Globalization.CultureInfo.InvariantCulture) * 2;
// timestamp
decimal timestamp = Math.Round(Convert.ToDecimal(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds), 0);
//Sign
Encoding ascii = Encoding.ASCII;
string secretKey = "lfaeGkjitNwvyG2lqDueMhSAOzRFlzL73w5pKRCAvSy7YrxyTkvwKCcHBHj...";
HMACSHA256 hmac = new HMACSHA256(ascii.GetBytes(secretKey));
// string query_string_LIMIT = "symbol="+symbol+"USDT&side=BUY&type=LIMIT&timeInForce=GTC&quantity="+quantity+"&price="+priceF+"&recvWindow=5000×tamp="+timestamp+"&signature=";
string result = "symbol=" + symbol + "USDT&side=BUY&type=MARKET&quantity=" + quantity + "&recvWindow=5000×tamp=" + timestamp + "&signature=";
String signature = BitConverter.ToString(hmac.ComputeHash(ascii.GetBytes(result))).Replace("-", "");
oSession.host = "fapi.binance.com";
string resultRequest = "symbol=" + symbol + "USDT&side=BUY&type=MARKET&quantity=" + quantity + "&recvWindow=5000×tamp=" + timestamp + "&signature=" + signature;
byte[] resulByte = System.Text.Encoding.ASCII.GetBytes(resultRequest);
//oSession.utilReplaceInRequest("api/v3/order","fapi/v1/order?"+resultFin);
oSession.url = oSession.url.Replace("api/v3/order", "fapi/v1/order?" + resultRequest);
FiddlerApplication.oProxy.SendRequest(oSession.RequestHeaders, resulByte, null);
}
}
Related
We are trying to get all products by ASINS number. It´s working in Postman but not working in .net using restsharp.
public static string url = "https://na.business-api.amazon.com/products/2020-08-26/products/getProductsByAsins";
public static string accessKey = "xxxxxxxxxxxxxxxxxxxxxxxxxx";
public static string secretkey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
public static string awsRegion = "us-east-1";
public static string awsServiceName = "execute-api";
string host = string.Join("/", url.Split('/').Select(Uri.EscapeDataString)) + "\n";
Uri endpoint = new Uri(url);
string s = endpoint.AbsoluteUri;
// Get and save dates ready for further use.
DateTimeOffset utcNowSaved = DateTimeOffset.UtcNow;
string amzLongDate = utcNowSaved.ToString("yyyyMMddTHHmmssZ");
string amzShortDate = utcNowSaved.ToString("yyyyMMdd");
string sha56key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
Dictionary < string, string > parameters = new Dictionary < string, string > ();
parameters.Add("Content-Type", "application/json");
parameters.Add("x-amz-access-token", accesstoken);
parameters.Add("x-amz-user-email", "example#gmail.com");
parameters.Add("X-Amz-Content-Sha256", sha56key);
parameters.Add("X-Amz-Date", amzLongDate);
parameters.Add("host", url);
// 1. Create Canonical Request
var canonicalRequest = new StringBuilder();
canonicalRequest.Append("POST" + "\n");
var headersToBeSigned = new List < string > ();
foreach(KeyValuePair < string, string > keyValuePair in parameters) {
canonicalRequest.Append(keyValuePair.Key.ToLowerInvariant());
canonicalRequest.Append(":");
canonicalRequest.Append(string.Join(",", keyValuePair.Value.Trim()));
canonicalRequest.Append("\n");
headersToBeSigned.Add(keyValuePair.Key.ToLowerInvariant());
}
canonicalRequest.Append("\n");
var signedHeaders = string.Join(";", headersToBeSigned);
canonicalRequest.Append(signedHeaders + "\n");
canonicalRequest.Append(sha56key);
// 2. String to sign.
string stringToSign = "AWS4-HMAC-SHA256" + "\n" + amzLongDate + "\n" + amzShortDate + "/" + awsRegion + "/" + awsServiceName + "/aws4_request" + "\n" + Hash(Encoding.UTF8.GetBytes(canonicalRequest.ToString()));
// 3. Signature with compounded elements.
var dateKey = HmacSha256(Encoding.UTF8.GetBytes("AWS4" + secretkey), `enter code here`
amzShortDate);
var dateRegionKey = HmacSha256(dateKey, awsRegion);
var dateRegionServiceKey = HmacSha256(dateRegionKey, awsServiceName);
var signingKey = HmacSha256(dateRegionServiceKey, "aws4_request");
var signature = ToHexString(HmacSha256(signingKey, stringToSign.ToString()));
// **************************************************** END SIGNING PORTION ****************************************************
// Add the Header to the request.
var credentialScope = amzShortDate + "/" + awsRegion + "/" + awsServiceName + "/aws4_request";
parameters.Add("Authorization", "AWS4-HMAC-SHA256 Credential=" + accessKey + "/" + credentialScope + ", SignedHeaders=" + signedHeaders + ", Signature=" + signature);
var client = new RestClient();
var request = new RestRequest(url, Method.Post);
foreach(KeyValuePair < string, string > keyValuePair in parameters) {
request.AddHeader(keyValuePair.Key, keyValuePair.Value);
}
var body = new AmazonASINSRequestDto();
body.productIds = new List < string > (new string[] {
"B087Z733CM",
"B0012YVGOW",
"B000YDJIYW",
"B07XQHYC95",
"B004MDLZ96",
"B07KSRFJ9Y",
"B00YH2JT9U",
"B002OB49KA",
"B00FU6PDLU"
});
body.productRegion = "US";
body.locale = "en_US";
body.facets = new List < string > (new string[] {
"OFFERS",
"IMAGES"
});
var jsonval = JsonConvert.SerializeObject(body);
//request.AddParameter("application/json", jsonval, ParameterType.RequestBody);
request.AddJsonBody(jsonval);
RestResponse response = await client.ExecuteAsync(request);
I am working with an IP camera that supports Audio output(Audio Back-channel). What I want to do is The live stream my PC microphone audio data over provided RTSP URL so that what ever said at PC microphone will be audible at camera speaker end. I have read about onvif streaming specification that tells me that once I got RTSP url of camera media I have to send my audio data over provided rtsp url for audio output at camera end. Also my camera supports Onvif profile T.
What I have tried so far is -
public static RtspClient rtspClient;
public static IWaveIn sourceStream;
private static void CallAudio()
{
string CameraIp = "192.168.1.69";
string UserName = "admin";
string Password = "admin123";
var ClientMessageInspector = new ClientMessageInspector(UserName, Password);
//Call Device Url and get Services.
string DeviceServiceUrl = "http://" + CameraIp + "/onvif/device_service";
var deviceClient = new DeviceClient("DeviceBinding", new EndpointAddress(DeviceServiceUrl));
deviceClient.Endpoint.Behaviors.Add(ClientMessageInspector);
var getServices = deviceClient.GetServices(false);
//Call media2 getStreamingUri.
string url = "http://" + CameraIp + "/onvif/media2_service";
var Media2Client = new Media2Client("Media2Binding", new EndpointAddress(url));
Media2Client.Endpoint.Behaviors.Add(ClientMessageInspector);
var media2GetProfiles = Media2Client.GetProfiles(null, null);
var resp = Media2Client.GetAudioDecoderConfigurationOptions(null, null);
var responseGetAudioStreamUri = Media2Client.GetStreamUri("tcp", profiles[0].token); //This gets rtsp url of media from camera.
rtspClient = new RtspClient(responseGetAudioStreamUri, UserName, Password);
sourceStream = new WaveInEvent();
sourceStream.WaveFormat = new WaveFormat(64, 8, 1); //8000 16
sourceStream.DataAvailable += new EventHandler<WaveInEventArgs>(SourceStream_DataAvailable);
sourceStream.StartRecording();
Console.ReadKey();
}
//This method gets data from PC microphone and enocodes it into Mu-Law G711 and send to rtsp url.
private static void SourceStream_DataAvailable(object sender, WaveInEventArgs e)
{
byte[] encoded = TwoWayAudio_Encode_MuLaw(e.Buffer, 0, e.BytesRecorded);
rtspClient.SendData(encoded, encoded.Length, 3);
}
private static byte[] TwoWayAudio_Encode_MuLaw(byte[] data, int offset, int length)
{
byte[] encoded = new byte[length / 2];
int outIndex = 0;
for (int n = 0; n < length; n += 2)
{
encoded[outIndex++] = MuLawEncoder.LinearToMuLawSample(BitConverter.ToInt16(data, offset + n));
}
return encoded;
}
The rtsp client that I am using in my project for Describe, Setup and Play of rtsp URL is taken from this github repo https://github.com/BogdanovKirill/RtspClientSharp.
Rtspclient.cs
using Rtsp;
using Rtsp.Messages;
using Rtsp.Sdp;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
namespace Rtsp
{
public class RtspClient
{
private RtspListener rtsp_client;
private RtspTcpTransport tcp_socket;
public string url;
public bool canPlay = false;
public string username;
public string password;
public ushort seqNo = 0;
public event EventHandler<string> RtspError;
public event EventHandler<byte[]> RtpDataReceived;
public Stopwatch stopwatch { get; private set; }
public RtspClient(string _url, string _username, string _password)
{
url = _url;
username = _username;
password = _password;
var uri = new Uri(_url);
tcp_socket = new RtspTcpTransport(uri.Host, 554); // 554);
if (tcp_socket.Connected == false)
{
Console.WriteLine("Error - did not connect");
return;
}
// Connect a RTSP Listener to the TCP Socket to send messages and listen for replies
rtsp_client = new RtspListener(tcp_socket);
rtsp_client.MessageReceived += Rtsp_client_MessageReceived;
rtsp_client.DataReceived += DataReceived;
rtsp_client.Start(); // start reading messages from the server
rtsp_client.AutoReconnect = true;
RtspRequest describe_message = new RtspRequestDescribe();
describe_message.RtspUri = uri;
describe_message.AddHeader("Accept: application/sdp");
describe_message.AddHeader("Require: www.onvif.org/ver20/backchannel");
rtsp_client.SendMessage(describe_message);
stopwatch = new Stopwatch();
stopwatch.Start();
}
private void DataReceived(object sender, RtspChunkEventArgs e)
{
int rtp_version = (e.Message.Data[0] >> 6);
int rtp_padding = (e.Message.Data[0] >> 5) & 0x01;
int rtp_extension = (e.Message.Data[0] >> 4) & 0x01;
int rtp_csrc_count = (e.Message.Data[0] >> 0) & 0x0F;
int rtp_marker = (e.Message.Data[1] >> 7) & 0x01;
int rtp_payload_type = (e.Message.Data[1] >> 0) & 0x7F;
uint rtp_sequence_number = ((uint)e.Message.Data[2] << 8) + (uint)(e.Message.Data[3]);
uint rtp_timestamp = ((uint)e.Message.Data[4] << 24) + (uint)(e.Message.Data[5] << 16) + (uint)(e.Message.Data[6] << 8) + (uint)(e.Message.Data[7]);
uint rtp_ssrc = ((uint)e.Message.Data[8] << 24) + (uint)(e.Message.Data[9] << 16) + (uint)(e.Message.Data[10] << 8) + (uint)(e.Message.Data[11]);
int rtp_payload_start = 4 // V,P,M,SEQ
+ 4 // time stamp
+ 4 // ssrc
+ (4 * rtp_csrc_count); // zero or more csrcs
uint rtp_extension_id = 0;
uint rtp_extension_size = 0;
if (rtp_extension == 1)
{
rtp_extension_id = ((uint)e.Message.Data[rtp_payload_start + 0] << 8) + (uint)(e.Message.Data[rtp_payload_start + 1] << 0);
rtp_extension_size = ((uint)e.Message.Data[rtp_payload_start + 2] << 8) + (uint)(e.Message.Data[rtp_payload_start + 3] << 0);
rtp_payload_start += 4 + (int)rtp_extension_size; // extension header and extension payload
}
Console.WriteLine("RTP Data"
+ " V=" + rtp_version
+ " P=" + rtp_padding
+ " X=" + rtp_extension
+ " CC=" + rtp_csrc_count
+ " M=" + rtp_marker
+ " PT=" + rtp_payload_type
+ " Seq=" + rtp_sequence_number
+ " Time=" + rtp_timestamp
+ " SSRC=" + rtp_ssrc
+ " Size=" + e.Message.Data.Length);
// If rtp_marker is '1' then this is the final transmission for this packet.
// If rtp_marker is '0' we need to accumulate data with the same timestamp
// ToDo - Check Timestamp matches
// Add to the tempoary_rtp List
if (rtp_payload_type == 98 || rtp_payload_type == 0)
{
byte[] rtp_payload = new byte[e.Message.Data.Length - rtp_payload_start]; // payload with RTP header removed
System.Array.Copy(e.Message.Data, rtp_payload_start, rtp_payload, 0, rtp_payload.Length); // copy payload
RtpDataReceived?.Invoke(null, rtp_payload);
}
}
public bool SendData(byte[] data, int count, int channel)
{
byte[] rtp_packet = new byte[12 + data.Length];
int rtp_version = 2;
int rtp_padding = 0;
int rtp_extension = 0;
int rtp_csrc_count = 0;
int rtp_marker = 1; // set to 1 if the last NAL in the array
//int rtp_payload_type = 98;
int rtp_payload_type = 0;
RTPPacketUtil.WriteHeader(rtp_packet, rtp_version, rtp_padding, rtp_extension, rtp_csrc_count, rtp_marker, rtp_payload_type);
RTPPacketUtil.WriteSequenceNumber(rtp_packet, seqNo);
seqNo++;
RTPPacketUtil.WriteTS(rtp_packet, (uint)stopwatch.ElapsedMilliseconds);
UInt32 empty_ssrc = 1293847657;
RTPPacketUtil.WriteSSRC(rtp_packet, empty_ssrc);
// Now append the raw NAL
System.Array.Copy(data, 0, rtp_packet, 12, data.Length);
if (canPlay)
{
rtsp_client.SendData(channel, rtp_packet);
return true;
}
else return false;
}
private void Rtsp_client_MessageReceived(object sender, RtspChunkEventArgs e)
{
RtspResponse message = e.Message as RtspResponse;
if (message.ReturnCode == 500)
{
RtspError?.Invoke(this, "Internal Server Error");
}
if (message.ReturnCode == 401)
{
Rtsp.Messages.RtspRequest msg = null;
switch (message.OriginalRequest.Method)
{
case "DESCRIBE":
msg = new RtspRequestDescribe();
break;
case "SETUP":
msg = new RtspRequestSetup();
break;
default:
break;
}
msg.RtspUri = new Uri(url);
var header = message.Headers["WWW-Authenticate"];
var _realm = GrabHeaderVar("realm", header);
var _nonce = GrabHeaderVar("nonce", header);
var ha1 = CalculateMd5Hash(string.Format("{0}:{1}:{2}", username, _realm, password));
var ha2 = CalculateMd5Hash(string.Format("{0}:{1}", message.OriginalRequest.Method, url));
var digestResponse = CalculateMd5Hash(string.Format("{0}:{1}:{2}", ha1, _nonce, ha2));
var digest = string.Format("Digest username=\"{0}\", realm=\"{1}\", nonce=\"{2}\", uri=\"{3}\", response=\"{4}\" ",
username, _realm, _nonce, url, digestResponse);
msg.AddHeader("Authorization: " + digest);
msg.AddHeader("Accept: application/sdp");
rtsp_client.SendMessage(msg);
return;
}
Console.WriteLine("Received " + message.OriginalRequest.ToString());
if (message.OriginalRequest != null && message.OriginalRequest is RtspRequestDescribe)
{
// Got a reply for DESCRIBE
// Examine the SDP
Console.Write(Encoding.UTF8.GetString(message.Data));
SdpFile sdp_data;
using (StreamReader sdp_stream = new StreamReader(new MemoryStream(message.Data)))
{
sdp_data = SdpFile.Read(sdp_stream);
}
// Process each 'Media' Attribute in the SDP.
// If the attribute is for Video, then send a SETUP
for (int x = 0; x < sdp_data.Medias.Count; x++)
{
if (sdp_data.Medias[x].MediaType == Rtsp.Sdp.Media.MediaTypes.audio || sdp_data.Medias[x].MediaType == Rtsp.Sdp.Media.MediaTypes.video)
{
// seach the atributes for control, fmtp and rtpmap
String control = ""; // the "track" or "stream id"
String fmtp = ""; // holds SPS and PPS
String rtpmap = ""; // holds the Payload format, 96 is often used with H264
foreach (Rtsp.Sdp.Attribut attrib in sdp_data.Medias[x].Attributs)
{
if (attrib.Key.Equals("control")) control = attrib.Value;
if (attrib.Key.Equals("fmtp")) fmtp = attrib.Value;
if (attrib.Key.Equals("rtpmap")) rtpmap = attrib.Value;
}
// Get the Payload format number for the Video Stream
String[] split_rtpmap = rtpmap.Split(' ');
var video_payload = 0;
bool result = Int32.TryParse(split_rtpmap[0], out video_payload);
// Send SETUP for the Video Stream
// using Interleaved mode (RTP frames over the RTSP socket)
Rtsp.Messages.RtspRequest setup_message = new Rtsp.Messages.RtspRequestSetup();
setup_message.RtspUri = new Uri(url + "/" + control);
//setup_message.AddHeader("Transport: RTP/AVP/TCP;interleaved=0");
setup_message.AddHeader("Require: www.onvif.org/ver20/backchannel");
rtsp_client.SendMessage(setup_message);
}
}
}
if (message.OriginalRequest != null && message.OriginalRequest is RtspRequestSetup)
{
// Got Reply to SETUP
Console.WriteLine("Got reply from Setup. Session is " + message.Session);
String session = message.Session; // Session value used with Play, Pause, Teardown
// Send PLAY
RtspRequest play_message = new RtspRequestPlay();
play_message.RtspUri = new Uri(url);
play_message.Session = session;
play_message.AddHeader("Require: www.onvif.org/ver20/backchannel");
rtsp_client.SendMessage(play_message);
}
if (message.OriginalRequest != null && message.OriginalRequest is RtspRequestPlay)
{
// Got Reply to PLAY
Console.WriteLine("Got reply from Play " + message.Command);
canPlay = true;
}
}
private static string GrabHeaderVar(string varName, string header)
{
var regHeader = new Regex(string.Format(#"{0}=""([^""]*)""", varName));
var matchHeader = regHeader.Match(header);
if (matchHeader.Success)
return matchHeader.Groups[1].Value;
throw new ApplicationException(string.Format("Header {0} not found", varName));
}
private static string CalculateMd5Hash(string input)
{
var inputBytes = Encoding.ASCII.GetBytes(input);
var hash = MD5.Create().ComputeHash(inputBytes);
var sb = new StringBuilder();
foreach (var b in hash)
sb.Append(b.ToString("x2"));
return sb.ToString();
}
public void Dispose()
{
rtsp_client.Stop();
rtsp_client.Dispose();
}
}
}
So before calling any rtsp method a i have added Rtsp Require: www.onvif.org/ver20/backchannel which is important for checking whether camera support AudioBack channel.
The output i get after calling Describe, Setup and play is Ok.
Received Rtsp.Messages.RtspRequestDescribe
v=0
o=- 0 0 IN IP4 192.168.1.69
s=LIVE VIEW
c=IN IP4 0.0.0.0
t=0 0
a=control:rtsp://192.168.1.69/rtsp_tunnel?p=0&h26x=4&aon=1&aud=0
m=video 0 RTP/AVP 35
a=rtpmap:35 H264/90000
a=control:rtsp://192.168.1.69/rtsp_tunnel?p=0&h26x=4&aon=1&aud=0&stream=video
a=recvonly
a=fmtp:35 packetization-mode=1;profile-level-id=4d0029;sprop-parameter-
sets=Z00AKZpkA8ARPy4C1BQEFAg=,aO48gA==
m=audio 0 RTP/AVP 96
a=rtpmap:96 mpeg4-generic/16000/1
a=fmtp:96 streamtype=5; profile-level-id=5; mode=AAC-hbr; config=1408; SizeLength=13; IndexLength=3;
IndexDeltaLength=3
a=control:rtsp://192.168.1.69/rtsp_tunnel?p=0&h26x=4&aon=1&aud=0&stream=audio
a=recvonly
m=audio 0 RTP/AVP 0
a=rtpmap:0 PCMU/8000/1
a=control:rtsp://192.168.1.69/rtsp_tunnel?p=0&h26x=4&aon=1&aud=0&stream=backchannel
a=sendonly
Received Rtsp.Messages.RtspRequestSetup
Got reply from Setup. Session is 12346e9856840dc
Received Rtsp.Messages.RtspRequestSetup
Got reply from Setup. Session is 12346e9856840dc
Received Rtsp.Messages.RtspRequestSetup
Got reply from Setup. Session is 12346e9856840dc
Received Rtsp.Messages.RtspRequestPlay
Got reply from Play RTSP/1.0 200 OK
Received Rtsp.Messages.RtspRequestPlay
Got reply from Play RTSP/1.0 200 OK
Received Rtsp.Messages.RtspRequestPlay
Got reply from Play RTSP/1.0 200 OK
After Getting Response from Play method i start sending my encoded data using send method in Rtsp client.
But the audio is not audible at camera end. My question is simple-
Is it is possible to send audio data over RTSP URL.
Is there any issue with the way I called my methods which is wrong?could any one please point that out.
Is there any easy way (or example/tutorial) that shows how to do audio backchannel over rtsp please provide it to.
Please don't mind I am new to Rtsp. Thanks in advance. If any issue with the question tell me I will edit it for move clear understanding.
I figured it out what I was doing wrong. Actually above mentioned steps are fine and camera returning Ok, what I was doing wrong was here in above code :
sourceStream.WaveFormat = new WaveFormat(64, 8, 1); //8000 16
Instead of 64 & 8 parameter it should be :
sourceStream.WaveFormat = new WaveFormat(8000, 16, 1); //8000 16
It was all voice smapling rate due to which voice send was not audible. Thankyou!
In the past I used for our certTool the com CERTENROLLLib to create the csr. Since Version 4.7.2 you can use the .net Framework.
It is possible to create the csr by passing all the necessary Attributes in the CreateSigningRequest Method and convert it into a pem base64 string.
Unfortunately I couldn't find the other way around, copy a csr in pem Format in a field and read all the csr Attributes from it (cn, san, organization, etc.)
I don't want to use the com lib CERTENROLLLib, openssl or other 3rd parties.
Here is what I have done (to get the csr pem string) found good examples in here and at MS Framework class description, thanks for your help
protected void createButton_Click(object sender, EventArgs e)
{
string csr_cn = txtb_csr_cn.Text;
string csr_c = txtb_csr_c.Text;
string csr_l = txtb_csr_l.Text;
string csr_o = txtb_csr_o.Text;
string csr_ou = txtb_csr_ou.Text;
string csr_s = txtb_csr_s.Text;
csr_san = sanMemo.Text.Replace(" ", "");
if (csr_san.IndexOf(csr_cn) == -1)
{
if (csr_san == "")
{
csr_san = csr_cn;
}
else
{
csr_san = csr_cn + "," + csr_san;
}
}
csr_key_size = Convert.ToInt32(combobox_csr_key.Text);
csr_info = "CN=" + csr_cn + "," + "OU=" + csr_ou + "," + "O=" + csr_o + "," + "L=" + csr_l + "," + "S=" + csr_s + "," + "C=" + csr_c;
notesMemo.Text = CreateCSR(); //CreateRequest();
}
public static string CreateCSR()
{
string[] arrSeperator = new string[] { "," };
RSA keySize = RSA.Create(csr_key_size);
CertificateRequest parentReq = new CertificateRequest(csr_info,
//"CN=Experimental Issuing Authority",
keySize,
HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1);
parentReq.CertificateExtensions.Add(
new X509BasicConstraintsExtension(true, false, 0, true));
parentReq.CertificateExtensions.Add(
new X509SubjectKeyIdentifierExtension(parentReq.PublicKey, false));
var sanBuilder = new SubjectAlternativeNameBuilder();
Array arrsan = csr_san.Split(arrSeperator, StringSplitOptions.RemoveEmptyEntries);
foreach (string sanvalue in arrsan)
{
sanBuilder.AddDnsName(sanvalue);
}
parentReq.CertificateExtensions.Add(sanBuilder.Build());
string csrdecrypt = PemEncodeSigningRequest(parentReq);
return csrdecrypt;
}
public static string PemEncodeSigningRequest(CertificateRequest request)
{
byte[] pkcs10 = request.CreateSigningRequest();
StringBuilder builder = new StringBuilder();
builder.AppendLine("-----BEGIN CERTIFICATE REQUEST-----");
string base64 = Convert.ToBase64String(pkcs10);
int offset = 0;
const int LineLength = 64;
while (offset < base64.Length)
{
int lineEnd = Math.Min(offset + LineLength, base64.Length);
builder.AppendLine(base64.Substring(offset, lineEnd - offset));
offset = lineEnd;
}
builder.AppendLine("-----END CERTIFICATE REQUEST-----");
string tester2 = builder.ToString();
return builder.ToString();
}
There is no pure-managed way to read a Certification Signing Request without third party libraries.
You could try using a P/Invoke to CryptDecodeObjectEx, possibly using the structure identifier of X509_CERT (per https://learn.microsoft.com/en-us/windows/desktop/SecCrypto/constants-for-cryptencodeobject-and-cryptdecodeobject).
But the CertificateRequest class is a PKCS#10 writer without a reader in .NET Framework.
Update (2023-01-30): LoadSigningRequestPem and friends were added in .NET 7.
I'm trying to pull the timeline of an authenticated user in a Windows 8.1/Windows Phone 8.1 Universal app. I believe I have everything set up correctly, but I keep getting a response of "code=32, message=Could not authenticate you" in Fiddler.
I think I'm just using the headers in the TwitterGetRequest function wrong, but I can't figure out the exact issue.
This is all based off the WebAuthentication Sample code from MSDN.
Here's the main function
private async Task GetTwitterUserNameAsync(string webAuthResultResponseData)
{
//
// Acquiring a access_token first
//
string responseData = webAuthResultResponseData.Substring(webAuthResultResponseData.IndexOf("oauth_token"));
string request_token = null;
string oauth_verifier = null;
String[] keyValPairs = responseData.Split('&');
for (int i = 0; i < keyValPairs.Length; i++)
{
String[] splits = keyValPairs[i].Split('=');
switch (splits[0])
{
case "oauth_token":
request_token = splits[1];
break;
case "oauth_verifier":
oauth_verifier = splits[1];
break;
}
}
String TwitterUrl = "https://api.twitter.com/oauth/access_token";
string response = await TwitterPostRequest(request_token, oauth_verifier, TwitterUrl);
String[] Tokens = response.Split('&');
string oauth_token_secret = null;
string access_token = null;
string screen_name = null;
for (int i = 0; i < Tokens.Length; i++)
{
String[] splits = Tokens[i].Split('=');
switch (splits[0])
{
case "screen_name":
screen_name = splits[1];
break;
case "oauth_token":
access_token = splits[1];
break;
case "oauth_token_secret":
oauth_token_secret = splits[1];
break;
}
}
//you can store access_token and oauth_token_secret for further use. See Scenario5(Account Management).
if (access_token != null)
{
DebugPrint("access_token = " + access_token);
}
if (oauth_token_secret != null)
{
DebugPrint("oauth_token_secret = " + oauth_token_secret);
}
if (screen_name != null)
{
//rootPage.NotifyUser(screen_name + " is connected!!", NotifyType.StatusMessage);
}
string timeline = await TwitterGetRequest(access_token, oauth_token_secret, oauth_verifier, "https://api.twitter.com/1.1/statuses/home_timeline.json");
List<SocialItem> tweets = new List<SocialItem>();
if (timeline.Length > 0)
{
JArray tweetArray = JArray.Parse(timeline);
for(int i=0;i<tweetArray.Count();i++)
{
JObject tweet = JObject.Parse(tweetArray[i].ToString());
JObject tweetAuthor = JObject.Parse(tweet["user"].ToString());
string imgUrl = tweetAuthor["profile_image_url"].ToString();
string message = tweet["text"].ToString();
string userName = tweetAuthor["screen_name"].ToString();
string displayName = tweetAuthor["name"].ToString();
string createdAtString = tweet["created_at"].ToString();
DateTime created;
if(!DateTime.TryParse(createdAtString, out created))
{
created = DateTime.MinValue;
}
tweets.Add(new SocialItem
{
ImageUrl = imgUrl,
MessageBody = message,
UserName = userName,
DisplayName = displayName,
MessageDate = created,
ProfileUrl = ("http://twitter.com/" + userName)
});
}
this.DataContext = tweets;
}
}
Here's the supporting functions:
private async Task<string> TwitterPostRequest(string request_token, string oauth_verifier, String TwitterUrl)
{
string timeStamp = GetTimeStamp();
string nonce = GetNonce();
String SigBaseStringParams = "oauth_consumer_key=" + Twitter.CLIENT_ID;
SigBaseStringParams += "&" + "oauth_nonce=" + nonce;
SigBaseStringParams += "&" + "oauth_signature_method=HMAC-SHA1";
SigBaseStringParams += "&" + "oauth_timestamp=" + timeStamp;
SigBaseStringParams += "&" + "oauth_token=" + request_token;
SigBaseStringParams += "&" + "oauth_version=1.0";
String SigBaseString = "POST&";
SigBaseString += Uri.EscapeDataString(TwitterUrl) + "&" + Uri.EscapeDataString(SigBaseStringParams);
String Signature = GetSignature(SigBaseString, Twitter.CLIENT_SECRET);
HttpStringContent httpContent = new HttpStringContent("oauth_verifier=" + oauth_verifier, Windows.Storage.Streams.UnicodeEncoding.Utf8);
httpContent.Headers.ContentType = HttpMediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");
string authorizationHeaderParams = "oauth_consumer_key=\"" + Twitter.CLIENT_ID + "\", oauth_nonce=\"" + nonce + "\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"" + Uri.EscapeDataString(Signature) + "\", oauth_timestamp=\"" + timeStamp + "\", oauth_token=\"" + Uri.EscapeDataString(request_token) + "\", oauth_version=\"1.0\"";
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new HttpCredentialsHeaderValue("OAuth", authorizationHeaderParams);
var httpResponseMessage = await httpClient.PostAsync(new Uri(TwitterUrl), httpContent);
string response = await httpResponseMessage.Content.ReadAsStringAsync();
return response;
}
private async Task<string> TwitterGetRequest(string request_token, string oauth_token_secret, string oauth_verifier, String TwitterUrl)
{
string timeStamp = GetTimeStamp();
string nonce = GetNonce();
String SigBaseStringParams = "oauth_consumer_key=" + Twitter.CLIENT_ID;
SigBaseStringParams += "&" + "oauth_nonce=" + nonce;
SigBaseStringParams += "&" + "oauth_signature_method=HMAC-SHA1";
SigBaseStringParams += "&" + "oauth_timestamp=" + timeStamp;
SigBaseStringParams += "&" + "oauth_token=" + request_token;
SigBaseStringParams += "&" + "oauth_version=1.0";
String SigBaseString = "GET&";
SigBaseString += Uri.EscapeDataString(TwitterUrl) + "&" + Uri.EscapeDataString(SigBaseStringParams);
String Signature = GetSignature(SigBaseString, oauth_token_secret);
//HttpStringContent httpContent = new HttpStringContent("oauth_verifier=" + oauth_verifier, Windows.Storage.Streams.UnicodeEncoding.Utf8);
//httpContent.Headers.ContentType = HttpMediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");
string authorizationHeaderParams = "oauth_consumer_key=\"" + Twitter.CLIENT_ID +
"\", oauth_nonce=\"" + nonce +
"\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"" + Uri.EscapeDataString(Signature) +
"\", oauth_timestamp=\"" + timeStamp +
"\", oauth_token=\"" + Uri.EscapeDataString(request_token) +
"\", oauth_version=\"1.0\"";
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new HttpCredentialsHeaderValue("OAuth", authorizationHeaderParams);
string response="";
try
{
response = await httpClient.GetStringAsync(new Uri(TwitterUrl));//httpClient.PostAsync(new Uri(TwitterUrl), httpContent);
}
catch (Exception ex)
{
DebugPrint(ex.Message);
}
//string response = await httpResponseMessage.Content.ReadAsStringAsync();
return response;
}
string GetNonce()
{
Random rand = new Random();
int nonce = rand.Next(1000000000);
return nonce.ToString();
}
string GetTimeStamp()
{
TimeSpan SinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
return Math.Round(SinceEpoch.TotalSeconds).ToString();
}
string GetSignature(string sigBaseString, string consumerSecretKey)
{
IBuffer KeyMaterial = CryptographicBuffer.ConvertStringToBinary(consumerSecretKey + "&", BinaryStringEncoding.Utf8);
MacAlgorithmProvider HmacSha1Provider = MacAlgorithmProvider.OpenAlgorithm("HMAC_SHA1");
CryptographicKey MacKey = HmacSha1Provider.CreateKey(KeyMaterial);
IBuffer DataToBeSigned = CryptographicBuffer.ConvertStringToBinary(sigBaseString, BinaryStringEncoding.Utf8);
IBuffer SignatureBuffer = CryptographicEngine.Sign(MacKey, DataToBeSigned);
string Signature = CryptographicBuffer.EncodeToBase64String(SignatureBuffer);
return Signature;
}
I have never received this kind of error but I have been developing with Tweetinvi and it is very easy to retrieve the timeline of the authenticated user.
Just do the following:
TwitterCredentials.SetCredentials("ACCESS_TOKEN", "ACCESS_TOKEN_SECRET", "CONSUMER_KEY", "CONSUMER_SECRET");
var tweets = Timeline.GetHomeTimeline();
Hope this helps.
I've spent the past couple nights on this, and it's driving me mad. Hopefully someone can shed some light on this.
I'm trying to write a Windows Phone 7 app to connect to Google. The OAuth routine is really giving me trouble.
I've seen quite a few twitter examples, but nothing specific to Google. The code is below - every time I make the request, Google says 'invalid signature.' The base URLs match, everything seems kosher - but it refuses to take it.
string baseReqUrl = "https://www.google.com/accounts/OAuthGetRequestToken";
string oauth_consumer_key = "CONSUMER_KEY";
string oauth_consumer_secret = "CONSUMER_SECRET";
string oauth_nonce = OAuthLibrary.OAuth.CreateNonce();
string oauth_signature_method = "HMAC-SHA1";
long oauth_timestamp = OAuthLibrary.OAuth.CreateTimestamp();
//string scope = "https%3A%2F%2Fwww.google.com%2Fanalytics%2Ffeeds%2F";
string scope = "https://www.google.com/analytics/feeds/";
string oauth_callback = "oob";
List<string> sig = new List<string>();
sig.Add(baseReqUrl);
sig.Add("oauth_callback=" + oauth_callback);
sig.Add("oauth_conusmer_key=" + oauth_consumer_key);
sig.Add("oauth_nonce=" + oauth_nonce);
sig.Add("oauth_signature_method=" + oauth_signature_method);
sig.Add("oauth_timestamp=" + oauth_timestamp.ToString());
sig.Add("scope=" + scope);
string baseReq = "GET";
int i = 0;
foreach (string s in sig)
{
if (i == 1)
{
baseReq = baseReq + "?" + s;
}
else
{
baseReq = baseReq + "&" + s;
}
i++;
}
HMACSHA1 h = new HMACSHA1(Encoding.UTF8.GetBytes(oauth_consumer_secret));
OAuth.OAuthBase b = new OAuth.OAuthBase();
string normalizedUrl = string.Empty;
string normalizedRequestParameters = string.Empty;
string sigBase = b.GenerateSignatureBase(new Uri(baseReq.Substring(4)), oauth_consumer_key, null, null, "GET", oauth_timestamp.ToString(), oauth_nonce, "HMAC-SHA1", out normalizedUrl, out normalizedRequestParameters);
string signature = b.GenerateSignatureUsingHash(sigBase, h);
string reqUrl = normalizedUrl + "?" + normalizedRequestParameters + "&oauth_signature=" + signature;
GetUrl(reqUrl); //this line just makes the request