#Verify an #Email Address with a #DNS #MX lookup in C#

Sending an email to an invalid email address has some bad side effects, the most important being, is that your message is not going through to its intended recipient, and on a larger scale, a bad email counts towards your bounce ratio with your SMTP provider, which in extreme cases can cause legal issues with EU PECR laws.
You can always, verify the format of an email address using a regex, but this has two issues – one, is that new TLD’s like “.museum” or “.家電” might break the regex, and secondly, even if the email is valid. Secondly, some domains are valid, but have no MX record set up to handle email. like “info@testtesttest.com” is going to pass any regex, but “testtesttest.com” has no ability to handle email.
So, here’s a bit of code in C# that verifies the domain part of the email;
public static bool VerifyEmailDomain(string domain)
{
// Install-Package ARSoft.Tools.Net
try
{
var resolver = new DnsStubResolver();
var records = resolver.Resolve<MxRecord>(domain, RecordType.Mx);
return records.Any();
}
catch {
return false;
}
}
Now, unfortunately, it’s not possible to check if bob@gmail.com is valid, even if fred@gmail.com using this technique, however, if it is really important, then you can check gmail accounts against the AvatarAPI.com API – to verify if the Gmail account has a profile attached.
This technique is the basis behind http://www.directtomx.com/ – a email sending API that bypasses intermediary SMTP servers.
Send a message with #PushBullet using c#
![]()
Pushbullet is an iOS / Android and Web based app, that is used for automated messaging. It’s pretty easy to use from within C#, here’s an example;
* curl –header ‘Access-Token: <your_access_token_here>’ \
–header ‘Content-Type: application/json’ \
–data-binary ‘{“body”:”Space Elevator, Mars Hyperloop, Space Model S (Model Space?)”,”title”:”Space Travel Ideas”,”type”:”note”}’ \
–request POST \
https://api.pushbullet.com/v2/pushes
*/var message = new
{
body = “Space Elevator, Mars Hyperloop, Space Model S (Model Space?)”,
title = “Space Travel Ideas”,
type = “note”
};
WebClient wc = new WebClient();
wc.Headers[“Access-Token”] = “o.xxxxxxxxxxxxxx”;
wc.Headers[“Content-Type”] = “application/json”;
var strPayload = JsonConvert.SerializeObject(message);
var strResponse = wc.UploadString(“https://api.pushbullet.com/v2/pushes”, strPayload);/*
{
“active”: true,
“iden”: “xxxxxxx”,
“created”: 1512656152.566,
“modified”: 1512656152.5928,
“type”: “note”,
“dismissed”: false,
“direction”: “self”,
“sender_iden”: “ujvhvGp18iy”,
“sender_email”: “xxxx@hotmail.com”,
“sender_email_normalized”: “xxxx@hotmail.com”,
“sender_name”: “xxxx xxxx”,
“receiver_iden”: “ujvhvGp18iy”,
“receiver_email”: “xxxx@hotmail.com”,
“receiver_email_normalized”: “xxx@hotmail.com”,
“title”: “Space Travel Ideas”,
“body”: “Space Elevator, Mars Hyperloop, Space Model S (Model Space?)”
}
*/
The above code requires the NUNIT package Install-Package Newtonsoft.Json, and you’ll need an access token from pushbullet under your account > Settings
#Bitcoin clipboard #Virus, and how to avoid it.

When checking stats on FreebieBitcoin.com – all of the Bitcoin Millionaires (> USD$ 1M) on the site shared the same Bitcoin wallet 13JF5274VuNthhwKkLrYyZW73smjSYAEen
This turned out to be something very sinister indeed.
A windows Virus, called Trojan.Coinbitclip – watches your windows clipboard for a Bitcoin wallet address, then when detected, replaces it with the hacker’s account. meaning, if you are about to make a bitcoin payment, you end up giving it to the hacker, rather than the person you intended to pay.
To avoid it, you should always copy and paste into notepad, compare the numbers, and if they are not identical, then run a full virus scan on your computer. Bitcoin addresses are designed not to look visually identical, so it should be easy to spot.
Here is some further reading on the subject:
https://steemit.com/bitcoin/@adnanefs/my-bitcoin-is-gone-sneaky-virus-story
https://bitcointalk.org/index.php?topic=1842977.0
https://www.symantec.com/security_response/writeup.jsp?docid=2016-020216-4204-99&tabid=2
Creating a #Facebook #Chatbot using #AWS #Lex and #Lambda

Chatbots are a novel way of interacting with your customers if you don’t have the staff to deal with them personally.
Creating one using Amazon LEX is really easy, and you can do it with no code whatsoever. – Although if you want it to do anything of use, then you’ll need to write a Lambda function.
First, log into AWS, open up LEX, then create a new Bot.
You’ll need to set up an Intent, and add an utterance that will activate this intent. You add slots – which are dynamic data provided by the user that provides you with the information you need to fulfil the user’s request.
You can test it out on the right hand side of the page, but the real kicker is getting the bot to work with Facebook. – So, you head on over to developers.facebook.com and create a new App. Select Products > Add product > Messenger
In Token Generation, select your Facebook Page, and press generate. You’ll need this token later. – Also grab the app secret key, you’ll need this in a moment.
Head back over to LEX, select Channels, then fill in the form, – Your Verify Token can be anything at all, just remember it for the next step. Press activate, and you’ll get an Endpoint URL.
Jump back to Facebook, and open up the webhooks tab. Create a new webhook, and enter the Verify Token, and the Endpoint URL. give permissions for the following: messages, messaging_postbacks, messaging_optins , and then select a page, and press subscribe to events.
Now, if you open Facebook messenger on your phone and start a chat with your business page, your bot should start replying to messages
Of course, to make it do anything useful, you have to write some code, To do this, you create a lambda function in AWS, and link it to the Fulfilment step in LEX. In this example, I am taking the data provided by the user, and building up a URL from it, that the user can click – so that a web-page can finish serving the customer.
I used this code; based on the orderFlowers NodeJs example.
function elicitSlot(sessionAttributes, intentName, slots, slotToElicit, message) {
return {
sessionAttributes,
dialogAction: {
type: ‘ElicitSlot’,
intentName,
slots,
slotToElicit,
message,
},
};
}function close(sessionAttributes, fulfillmentState, message, responseCard) {
return {
sessionAttributes,
dialogAction: {
type: ‘Close’,
fulfillmentState,
message,
responseCard
},
};
}function delegate(sessionAttributes, slots) {
return {
sessionAttributes,
dialogAction: {
type: ‘Delegate’,
slots,
},
};
}function FindFlight(intentRequest, callback) {
const source = intentRequest.invocationSource;
const depart = intentRequest.currentIntent.slots.departure;
const destination = intentRequest.currentIntent.slots.destination;
const departureDate = intentRequest.currentIntent.slots.departureDate;
const returnDate = intentRequest.currentIntent.slots.returnDate;
const Adults = intentRequest.currentIntent.slots.Adults;
const Children = intentRequest.currentIntent.slots.Children;
const infants = intentRequest.currentIntent.slots.infants;if (source === ‘DialogCodeHook’) {
const outputSessionAttributes = intentRequest.sessionAttributes;
callback(delegate(outputSessionAttributes, intentRequest.currentIntent.slots));
return;
}
callback(close(intentRequest.sessionAttributes, ‘Fulfilled’,
{
contentType: ‘PlainText’,
content: `Click the following link to see our flight offers`
},
{
“version”: 3,
“contentType”: “application/vnd.amazonaws.card.generic”,
“genericAttachments”: [
{
“title”:`${depart} to ${destination}`,
“subTitle”:`${departureDate} – ${returnDate}`,
“attachmentLinkUrl”:`http://www.somewebsite.com/{$depart}/{$destination}/${departureDate}/${returnDate}`,}
]
}));
}/**
* Called when the user specifies an intent for this skill.
*/
function dispatch(intentRequest, callback) {
console.log(`dispatch userId=${intentRequest.userId}, intentName=${intentRequest.currentIntent.name}`);const intentName = intentRequest.currentIntent.name;
// Dispatch to your skill’s intent handlers
if (intentName === ‘YOUR-INTENT’) {
return FindFlight(intentRequest, callback);
}
throw new Error(`Intent with name ${intentName} not supported`);
}
exports.handler = (event, context, callback) => {
// TODO implement
dispatch(event, (response) => callback(null, response));
};
#Verify a bank account number in C# using #Stripe

Say you collect payout data from your affiliates or partners, and you would like to make sure that the bank details are correct, so that you do not have the embarrassment and cost of a bounced payment.
Here is a trick on how to do this, using Stripe – This is not actually using Stripe to make the payout, but it’s using Stripe Connect to verify the bank account details.
First set up a Stripe account, then create a sub account via Stripe connect. You will need this account id, and your private key. Do not use your main account id, since your bank account details will be overwritten.
Here’s the main code;
public static string Verify(string BankCountry, string BankSortCode, string BankAccountNumber){var wc = new WebClient();string strResult;try{ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; // comparable to modern browsersvar myCreds = new NetworkCredential(PrivateKey, “”);wc.Credentials = myCreds;var strUrl = “https://api.stripe.com/v1/accounts/{0}”;strUrl = string.Format(strUrl, stripe_user_id);var strPostdata = “”;// to-do: Possible-bug: Does this add new bank accounts every time you try to update the account?if (BankAccountNumber != null && !BankAccountNumber.StartsWith(“*”)){strPostdata += “&external_account[object]=bank_account”;strPostdata += “&external_account[country]=” + BankCountry;strPostdata += “&external_account[currency]=” + CurrencyFromBankCountry(BankCountry);strPostdata += “&external_account[routing_number]=” + BankSortCode.Replace(“-“, “”).Replace(” “, “”);strPostdata += “&external_account[account_number]=” + BankAccountNumber;}wc.Headers[“Content-Type”] = “application/x-www-form-urlencoded”;strResult = wc.UploadString(strUrl, strPostdata);}catch (WebException exception){strResult = GetExceptionDetails(exception);var jError = JObject.Parse(strResult);thrownew Exception(jError[“error”][“message”].ToString());}var userJson = GetAccountDetails();var jUser = JObject.Parse(userJson);foreach (var bankAccont in jUser[“bank_accounts”][“data”]){var strStripeLast4 = bankAccont[“last4”].ToString();var strPassedLast4 = BankAccountNumber.Substring(BankAccountNumber.Length – 4);if (strPassedLast4 == strStripeLast4){return bankAccont.ToString();}}return”Unknown failure”;}
private static string GetAccountDetails(){/*-u sk_test_jCTjZ7050Z9zbRyj3me2JFEW:*/var wc = new WebClient();string strResult;try{var myCreds = new NetworkCredential(PrivateKey, “”);wc.Credentials = myCreds;var strUrl = “https://api.stripe.com/v1/accounts/”;strUrl += stripe_user_id;strResult = wc.DownloadString(strUrl);}catch (WebException exception){strResult = GetExceptionDetails(exception);}return strResult;}
private static string GetExceptionDetails(WebException exception){string strResult = “”;if (exception.Response != null){var responseStream = exception.Response.GetResponseStream();if (responseStream != null){using (var reader = new StreamReader(responseStream)){strResult = reader.ReadToEnd();}}}return strResult;}
privatestaticstring CurrencyFromBankCountry(string BankCountry){switch (BankCountry){case”US”: return”USD”;case”IE”: return”EUR”;case”GB”: return”GBP”;case”AU”: return”AUD”;case”CA”: return”CAD”;case”DK”: return”DKK”;case”FI”: return”EUR”;case”FR”: return”EUR”;case”JP”: return”JPY”;case”NO”: return”NOK”;case”SG”: return”SGD”;case”ES”: return”EUR”;case”SE”: return”SEK”;case”AT”: return”EUR”;case”BE”: return”EUR”;case”DE”: return”EUR”;case”HK”: return”HKD”;case”IT”: return”EUR”;case”LU”: return”EUR”;case”NL”: return”EUR”;case”PT”: return”EUR”;}throw new Exception(“Unrecognised bank country”);}
Send #email via #JQuery

This was bit of an aborted project, since I see that the JQuery Plugin registry is now closed for new submissions. But, I created a little JQuery Plugin as a Wrapper for the SMTPJS library with this;
(function ( $ ) {
$.getScript( “https://smtpjs.com/v2/smtp.js”, function( data, textStatus, jqxhr ) {
$.fn.Email = Email;
});
$.fn.Email = function() {
return “Not Loaded yet”;
};
}( jQuery ));
Which can be called as follows;
$.fn.Email.send(“from@you.com”,
“to@them.com”,
“Subject line”,
“Body in HTML”,
{
token: “GUID from SMTPJS.com”,
callback: function done(message) { alert(message) }
});
The GIT repo is here https://github.com/infiniteloopltd/SmtpJQuery/
#Transactional Email in #Javascript

Transactional email differs from promotional / marketing email, in the sense that it is typically not sent it batches, but is sent in response to a user signing up to your website, or an event such as a low credit warning, or notification.
Normally, people think of email as a server side exercise, but you can also use Javascript to send email too – with the help of SMTPJS.com
Here’s a sample script using Elastic Email’s SMTP with SMTPJS –
Email.send(
“me@gmail.com”,
“you@gmail.com”,
“This is a subject”,
“this is the body”,
“smtp25.elasticemail.com”,
“username@gmail.com”,
“989accc0-cba1-4fbf-abf2-7bad4fc80526”,
function(data){ alert(data) });
It almost needs no explanation, it’s so simple!
If you don’t have access to an SMTP server, you can create one by opening an account at Elastic Email.com, then pressing Settings > SMTP/API, and using the SMTP configuration shown. Get SMTP Credentials
Determine what version of #TLS your code is using.

If your code connects to a HTTPS web service, it’s possible that you are still not being fully secure. The thing is – HTTPS comes in a few different “Flavours”, or specifically TLS versions.
If you connect to a HTTPS service, but use an old TLS version, then you’re not being as secure as you could be.
However, if the HTTPS endpoint doesn’t complain about your TLS version, it’s often pretty hard to see exactly what TLS version you are using, and the last thing you want is to break open WireShark and try and pick apart the packets to see.
That’s where this handy API from Jeff Hodges comes in, at https://www.howsmyssl.com/a/check
If you make a call from C#, you may see a result like this
{
“given_cipher_suites”: [
“TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA”,
“TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA”,
“TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA”,
“TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA”,
“TLS_RSA_WITH_AES_256_CBC_SHA”,
“TLS_RSA_WITH_AES_128_CBC_SHA”,
“TLS_RSA_WITH_3DES_EDE_CBC_SHA”,
“TLS_RSA_WITH_RC4_128_SHA”,
“TLS_RSA_WITH_RC4_128_MD5”
],
“ephemeral_keys_supported”: true,
“session_ticket_supported”: true,
“tls_compression_supported”: false,
“unknown_cipher_suite_supported”: false,
“beast_vuln”: false,
“able_to_detect_n_minus_one_splitting”: true,
“insecure_cipher_suites”: {
“TLS_RSA_WITH_3DES_EDE_CBC_SHA”: [
“uses 3DES which is vulnerable to the Sweet32 attack but was not configured as a fallback in the ciphersuite order”
],
“TLS_RSA_WITH_RC4_128_MD5”: [
“uses RC4 which has insecure biases in its output”
],
“TLS_RSA_WITH_RC4_128_SHA”: [
“uses RC4 which has insecure biases in its output”
]
},
“tls_version”: “TLS 1.0”,
“rating”: “Bad”
}
You can see, I get a “Bad” rating here, because I’m using TLS 1.0, and some obsolete cyphers.
I put in the following line to use TLS 1.2:
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
And received;
{
“given_cipher_suites”: [
“TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384”,
“TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256”,
“TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384”,
“TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256”,
“TLS_DHE_RSA_WITH_AES_256_GCM_SHA384”,
“TLS_DHE_RSA_WITH_AES_128_GCM_SHA256”,
“TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384”,
“TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256”,
“TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384”,
“TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256”,
“TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA”,
“TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA”,
“TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA”,
“TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA”,
“TLS_RSA_WITH_AES_256_GCM_SHA384”,
“TLS_RSA_WITH_AES_128_GCM_SHA256”,
“TLS_RSA_WITH_AES_256_CBC_SHA256”,
“TLS_RSA_WITH_AES_128_CBC_SHA256”,
“TLS_RSA_WITH_AES_256_CBC_SHA”,
“TLS_RSA_WITH_AES_128_CBC_SHA”,
“TLS_RSA_WITH_3DES_EDE_CBC_SHA”,
“TLS_RSA_WITH_RC4_128_SHA”,
“TLS_RSA_WITH_RC4_128_MD5”
],
“ephemeral_keys_supported”: true,
“session_ticket_supported”: true,
“tls_compression_supported”: false,
“unknown_cipher_suite_supported”: false,
“beast_vuln”: false,
“able_to_detect_n_minus_one_splitting”: false,
“insecure_cipher_suites”: {
“TLS_RSA_WITH_3DES_EDE_CBC_SHA”: [
“uses 3DES which is vulnerable to the Sweet32 attack but was not configured as a fallback in the ciphersuite order”
],
“TLS_RSA_WITH_RC4_128_MD5”: [
“uses RC4 which has insecure biases in its output”
],
“TLS_RSA_WITH_RC4_128_SHA”: [
“uses RC4 which has insecure biases in its output”
]
},
“tls_version”: “TLS 1.2”,
“rating”: “Bad”
}
Still using some old Cyphers, but at least using TLS 1.2 now.
If you see the same API when called from Chome, you see:
{
“given_cipher_suites”:[
“TLS_GREASE_IS_THE_WORD_AA”,
“TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256”,
“TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256”,
“TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384”,
“TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384”,
“TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256”,
“TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256”,
“TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA”,
“TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA”,
“TLS_RSA_WITH_AES_128_GCM_SHA256”,
“TLS_RSA_WITH_AES_256_GCM_SHA384”,
“TLS_RSA_WITH_AES_128_CBC_SHA”,
“TLS_RSA_WITH_AES_256_CBC_SHA”,
“TLS_RSA_WITH_3DES_EDE_CBC_SHA”
],
“ephemeral_keys_supported”:true,
“session_ticket_supported”:true,
“tls_compression_supported”:false,
“unknown_cipher_suite_supported”:false,
“beast_vuln”:false,
“able_to_detect_n_minus_one_splitting”:false,
“insecure_cipher_suites”:{},
“tls_version”:“TLS 1.2”,
“rating”:“Probably Okay”
}
Interestingly, you can also use this to see issues with Search Engine Spider bots, – look at the report from Yandex (Russian Search Engine)
Given Cipher Suites
The cipher suites your client said it supports, in the order it sent them, are:
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
- TLS_DH_DSS_WITH_AES_256_GCM_SHA384
- TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
- TLS_DH_RSA_WITH_AES_256_GCM_SHA384
- TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
- TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
- TLS_DH_RSA_WITH_AES_256_CBC_SHA256
- TLS_DH_DSS_WITH_AES_256_CBC_SHA256
- TLS_DHE_RSA_WITH_AES_256_CBC_SHA
- TLS_DHE_DSS_WITH_AES_256_CBC_SHA
- TLS_DH_RSA_WITH_AES_256_CBC_SHA
- TLS_DH_DSS_WITH_AES_256_CBC_SHA
- TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
- TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA
- TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA
- TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA
- TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
- TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
- TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
- TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
- TLS_RSA_WITH_AES_256_GCM_SHA384
- TLS_RSA_WITH_AES_256_CBC_SHA256
- TLS_RSA_WITH_AES_256_CBC_SHA
- TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
- TLS_DH_DSS_WITH_AES_128_GCM_SHA256
- TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
- TLS_DH_RSA_WITH_AES_128_GCM_SHA256
- TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
- TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
- TLS_DH_RSA_WITH_AES_128_CBC_SHA256
- TLS_DH_DSS_WITH_AES_128_CBC_SHA256
- TLS_DHE_RSA_WITH_AES_128_CBC_SHA
- TLS_DHE_DSS_WITH_AES_128_CBC_SHA
- TLS_DH_RSA_WITH_AES_128_CBC_SHA
- TLS_DH_DSS_WITH_AES_128_CBC_SHA
- TLS_DHE_RSA_WITH_SEED_CBC_SHA
- TLS_DHE_DSS_WITH_SEED_CBC_SHA
- TLS_DH_RSA_WITH_SEED_CBC_SHA
- TLS_DH_DSS_WITH_SEED_CBC_SHA
- TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
- TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA
- TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA
- TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA
- TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
- TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
- TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
- TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
- TLS_RSA_WITH_AES_128_GCM_SHA256
- TLS_RSA_WITH_AES_128_CBC_SHA256
- TLS_RSA_WITH_AES_128_CBC_SHA
- TLS_RSA_WITH_SEED_CBC_SHA
- TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
- TLS_RSA_WITH_IDEA_CBC_SHA
- TLS_ECDHE_RSA_WITH_RC4_128_SHA
- TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
- TLS_ECDH_RSA_WITH_RC4_128_SHA
- TLS_ECDH_ECDSA_WITH_RC4_128_SHA
- TLS_RSA_WITH_RC4_128_SHA
- TLS_RSA_WITH_RC4_128_MD5
- TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
- TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
- TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
- TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
- TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA
- TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA
- TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
- TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
- TLS_RSA_WITH_3DES_EDE_CBC_SHA
- TLS_EMPTY_RENEGOTIATION_INFO_SCSV
π = 6.2831… ? Have we got it wrong?

Recently reading a book by Steve mould “The Element In the Room”, he proposes that our definition of pi was a mistake, and instead it should have been double it’s value.
How can this be?, surely someone would have noticed. Well, it all comes down to definition. Pi is defined as the ratio between the diameter of a circle to the circumference. However, it could have just as easily be defined as the ratio of the radius of a circle divided by the diameter, and when that happens, many mathematical formulas become simplified.
Here’s a great video of Steve Mould arguing his case for Tau, or the double pi constant.
Implementing a #HTTPS #Tunnel using c#

You very rarely have to work at TCP/IP level whenever writing network code in C#, and if you find yourself doing it, you’ve probably taken a very wrong turn. However, since information is sparse about the format of low level TCP requests, I’m writing this article.
This particular code snippet shows how to make a HTTPS tunnel via a proxy server in C#. It involves these steps:
- Send a CONNECT command instructing the proxy to connect to a remote server on a given port, i.e. 443 for SSL, and forward all subsequent traffic to this host and port.
- Read the response from the proxy, it should be a line saying “200 Tunnel Established”
- Pass the stream to a SSL stream object, and call AuthenticateAsClient
- Send HTTP data as normal.
Here’s some code to connect to ICanHazIP via SSL.
private static string TestIp(WebProxy proxy)
{
var tcp = new TcpClient(proxy.Address.Host, proxy.Address.Port);
var stream = tcp.GetStream();
var connect = Encoding.ASCII.GetBytes(“CONNECT http://www.icanhazip.com:443 HTTP/1.0\n\n”);
stream.Write(connect, 0, connect.Length);
var rawStream = new StreamReader(stream);
var strConnect = rawStream.ReadLine();
var ssl = new SslStream(stream);
ssl.AuthenticateAsClient(“www.icanhazip.com”);
var send = Encoding.ASCII.GetBytes(“GET / HTTP/1.0\r\n” +
“Host:www.icanhazip.com\r\n” +
“\r\n”);
ssl.Write(send, 0, send.Length);
var sr = new StreamReader(ssl);
var str = sr.ReadToEnd();
tcp.Close();
ssl.Close();
return str;
}
If you’re interested in low level socket programming in C#, check out by book: