HTTPS/Client-authenticated

From Rosetta Code
Task
HTTPS/Client-authenticated
You are encouraged to solve this task according to the task description, using any language you may know.

Demonstrate how to connect to a web server over HTTPS where that server requires that the client present a certificate to prove who (s)he is. Unlike with the HTTPS request with authentication task, it is not acceptable to perform the authentication by a username/password or a set cookie.

This task is in general useful for use with webservice clients as it offers a high level of assurance that the client is an acceptable counterparty for the server. For example, Amazon Web Services uses this style of authentication.

C#[edit]

Works with: C sharp version 3.0
 
using System;
using System.Net;
 
class Program
{
class MyWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri address)
{
HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address);
request.ClientCertificates.Add(new X509Certificate());
return request;
}
}
static void Main(string[] args)
{
var client = new MyWebClient();
 
var data = client.DownloadString("https://example.com");
 
Console.WriteLine(data);
}
}
 


Go[edit]

package main
 
import (
"crypto/tls"
"io/ioutil"
"log"
"net/http"
)
 
func main() {
 
// load key pair
cert, err := tls.LoadX509KeyPair(
"./client.local.tld/client.local.tld.crt",
"./client.local.tld/client.local.tld.key",
)
 
if err != nil {
log.Fatal("Error while loading x509 key pair", err)
}
 
// Create TLS Config in order to had client certificate
tlsConfig := &tls.Config{Certificates: []tls.Certificate{cert}}
 
tlsConfig.BuildNameToCertificate()
transport := &http.Transport{TLSClientConfig: tlsConfig}
 
// create http client with our custom transport with TLS config
client := &http.Client{Transport: transport}
 
res, err := client.Get("https://www.example.com/")
if err != nil {
log.Fatal(err)
}
contents, err := ioutil.ReadAll(res.Body)
log.Print(string(contents))
 
}
 

Kotlin[edit]

// version 1.2.0
 
import java.security.KeyStore
import javax.net.ssl.KeyManagerFactory
import javax.net.ssl.SSLContext
import javax.net.ssl.HttpsURLConnection
import java.net.URL
import java.io.FileInputStream
import java.io.InputStreamReader
import java.io.BufferedReader
 
fun getSSLContext(p12Path: String, password: String): SSLContext {
val ks = KeyStore.getInstance("pkcs12")
val fis = FileInputStream(p12Path)
val pwd = password.toCharArray()
ks.load(fis, pwd)
val kmf = KeyManagerFactory.getInstance("PKIX")
kmf.init(ks, pwd)
val sc = SSLContext.getInstance("TLS")
sc.init(kmf.keyManagers, null, null)
return sc
}
 
fun main(args: Array<String>) {
// The .p12 file contains the client certificate and private key
val sc = getSSLContext("whatever.p12", "password")
val url = URL("https://somehost.com")
val con = url.openConnection() as HttpsURLConnection
con.sslSocketFactory = sc.socketFactory
val isr = InputStreamReader(con.inputStream)
val br = BufferedReader(isr)
while (true) {
val line = br.readLine()
if (line == null) break
println(line)
}
}

Lasso[edit]

local(sslcert = file('myCert.pem'))
local(x = curl('https://sourceforge.net'))
#x->set(CURLOPT_SSLCERT, #sslcert->readstring)
#sslcert->close
#x->result->asString

Mathematica / Wolfram Language[edit]

a = RunThrough["curl -E myCert.pem https://www.example.com", 1]
For[ i=0, i < Length[a] , i++, SomeFunction[a]]

Perl[edit]

#!/usr/bin/env perl -T
use 5.018_002;
use warnings;
use LWP;
 
our $VERSION = 1.000_000;
 
my $ua = LWP::UserAgent->new(
ssl_opts => {
SSL_cert_file => 'certificate.pem',
SSL_key_file => 'key.pem',
verify_hostname => 1,
}
);
my $req = HTTP::Request->new( GET => 'https://www.example.com' );
my $res = $ua->request($req);
if ( $res->is_success ) {
say $res->content;
}
else {
say $res->status_line;
}

Perl 6[edit]

 
# cert creation commands
 
# openssl req -newkey rsa:4096 -keyout my_key.pem -out my_csr.pem -nodes -subj "/CN=ME"
 
# openssl x509 -req -in my_csr.pem -signkey my_key.pem -out my_cert.pem
 
use v6;
use OpenSSL;
 
my $host = "github.com";
 
my $ssl = OpenSSL.new(:client);
 
$ssl.use-certificate-file("./my_cert.pem");
$ssl.use-privatekey-file("./my_key.pem");
$ssl.check-private-key;
 
 
my $s = IO::Socket::INET.new(:$host, :port(443));
 
$ssl.set-socket($s);
$ssl.set-connect-state;
$ssl.connect;
$ssl.write("GET / HTTP/1.1\r\n\r\n");
say $ssl.read(1024);
$ssl.close;
$s.close;
 
 

Phix[edit]

Library: libcurl

Exactly the same as the HTTP#Phix task, except for the CURLOPT_SSLCERT part.

include builtins\libcurl.e
curl_global_init()
atom curl = curl_easy_init()
curl_easy_setopt(curl, CURLOPT_URL, "https://sourceforge.net")
integer fn = open("myCert.pem","r")
curl_easy_setopt(curl, CURLOPT_SSLCERT, get_text(fn))
close(fn)
object res = curl_easy_perform_ex(curl)
curl_easy_cleanup(curl)
curl_global_cleanup()
 
puts(1,res)

PicoLisp[edit]

(in '(curl "-E" "myCert.pem" "https://www.example.com")
(while (line)
(doSomeProcessingWithLine @) ) )

Python[edit]

import httplib
 
connection = httplib.HTTPSConnection('www.example.com',cert_file='myCert.PEM')
connection.request('GET','/index.html')
response = connection.getresponse()
data = response.read()
 

Racket[edit]

Skeleton code to connect to a server:

 
#lang racket
(require openssl/mzssl)
(define ctx (ssl-make-client-context))
(ssl-set-verify! ctx #t) ; verify the connection
(ssl-load-verify-root-certificates! ctx "my-cert.pem")
(define-values [I O] (ssl-connect "www.example.com" 443 ctx))
 

Ruby[edit]

require 'uri'
require 'net/http'
 
uri = URI.parse('https://www.example.com')
pem = File.read("/path/to/my.pem")
cert = OpenSSL::X509::Certificate.new(pem)
key = OpenSSL::PKey::RSA.new(pem)
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true,
cert: cert, key: key) do |http|
request = Net::HTTP::Get.new uri
http.request request
end

Scala[edit]

import java.io.FileInputStream
import java.net.URL
import java.security.KeyStore
 
import javax.net.ssl.{HttpsURLConnection, KeyManagerFactory, SSLContext}
 
import scala.io.BufferedSource
 
object ClientAuthenticated extends App {
 
val con: HttpsURLConnection =
new URL("https://somehost.com").openConnection().asInstanceOf[HttpsURLConnection]
 
def getSSLContext(p12Path: String, password: String): SSLContext = {
val ks = KeyStore.getInstance("pkcs12")
val pwd = password.toCharArray
ks.load(new FileInputStream(p12Path), pwd)
val kmf = KeyManagerFactory.getInstance("PKIX")
kmf.init(ks, pwd)
val sc = SSLContext.getInstance("TLS")
sc.init(kmf.getKeyManagers, null, null)
sc
}
 
// The .p12 file contains the client certificate and private key
HttpsURLConnection.setDefaultSSLSocketFactory(getSSLContext("whatever.p12", "password").getSocketFactory)
new BufferedSource(con.getInputStream).getLines.foreach(println(_))
 
}

Tcl[edit]

Uses the Tls package.

package require http
package require tls
 
set cert myCert.p12
http::register https 443 [list \
 ::tls::socket -certfile $cert -password getPass]
proc getPass {} {
return "myPassword"; # Just a noddy example...
}
 
# Make a secure authenticated connection
set token [http::geturl https://verysecure.example.com/]
 
# Now as for conventional use of the “http” package
set data [http::data $token]
http::cleanup $token

zkl[edit]

Uses libCurl.

var CURL=Import("zklCurl"), c=CURL();
c.setOpt("SSLCERT","certFile.pem"); c.setOpt("SSLCERTTYPE","pem");
c.get("http://zenkinetic.com"); // lame example to show how to read