OpenSSL für Webassembly compilieren

Submitted by admin on Fr, 13.04.2018 - 09:19

Mit dem folgenden Skript kann man OpenSSL für Webassembly compilieren.

Voraussetzungen

Das Skript mk-openssl-webassemby.sh:

#!/bin/bash

#################################################################
# prerequisites
# * Emscripten
#################################################################

# ==> Select latest version for security reasons
OPENSSL_VERSION="1.1.0h"

MY_HOME="$HOME"

cd "${MY_HOME}/webass-test" || exit 1

if [ ! -f openssl-${OPENSSL_VERSION}.tar.gz ]; then
  wget https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz
fi

rm -rf "openssl-${OPENSSL_VERSION}"
tar xvf "openssl-${OPENSSL_VERSION}.tar.gz"
cd openssl-${OPENSSL_VERSION}

export CC=emcc
export CXX=emcc
export LINK=${CXX}
export ARCH_FLAGS=""
export ARCH_LINK=""
export CPPFLAGS=" ${ARCH_FLAGS} "
export CXXFLAGS=" ${ARCH_FLAGS} "
export CFLAGS=" ${ARCH_FLAGS} "
export LDFLAGS=" ${ARCH_LINK} "

./Configure purify

PATH=$TOOLCHAIN_PATH:$PATH make

 

Die generierten Files in dem Verzeichnis kann man nun für die eigene Webassembly Anwendung verwenden.

Anwendung

hello.cpp

#include <stdio.h>
#include <string.h>
#include <string>
#include <stdlib.h>
#include <time.h>

#include <openssl/sha.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>

#include "ssl.h"


using namespace std;


void sha256(char *string, char outputBuffer[SHA256_DIGEST_LENGTH+1]) {
    unsigned char hash[SHA256_DIGEST_LENGTH];
    SHA256_CTX sha256;
    SHA256_Init(&sha256);
    SHA256_Update(&sha256, string, strlen(string));
    SHA256_Final(hash, &sha256);
    int i = 0;
    for(i = 0; i < SHA256_DIGEST_LENGTH; i++) {
        sprintf(outputBuffer + (i * 2), "%02x", hash[i]);
    }
    outputBuffer[SHA256_DIGEST_LENGTH] = 0;
}


string getTime() {
    static char buf[256];
    char fmt[] = "%a %b %d %H:%M:%S %Z %Y";
    time_t now = time(NULL);
    struct tm *tp;
    tp = localtime(&now);
    strftime(buf, sizeof(buf), fmt, tp);
    return buf;
}

int main(int argc, char **argv) {
    static string hello="Hello OpenSSL world "+getTime();
    static unsigned char buffer[65];

    char *chello = new char [hello.length()+1];
    std::strcpy (chello, hello.c_str());
    printf("%s\n", chello);
    sha256(chello, (char *)buffer);
    printf("sha256: %s\n", buffer);

    doTest();

    return 0;
}

ssl.cpp

#include <cstdio>
#include <iostream>
#include <openssl/pem.h>
#include <openssl/x509.h>

/* Generates a 2048-bit RSA key. */
EVP_PKEY * generate_key(int keySize)
{
    /* Allocate memory for the EVP_PKEY structure. */
    EVP_PKEY * pkey = EVP_PKEY_new();
    if(!pkey)
    {
        return NULL;
    }
    
    /* Generate the RSA key and assign it to pkey. */
    RSA * rsa = RSA_generate_key(keySize, RSA_F4, NULL, NULL);
    if(!EVP_PKEY_assign_RSA(pkey, rsa))
    {
        EVP_PKEY_free(pkey);
        return NULL;
    }
    
    /* The key has been generated, return it. */
    return pkey;
}

/* Generates a self-signed x509 certificate. */
X509 * generate_x509(EVP_PKEY * pkey)
{
    /* Allocate memory for the X509 structure. */
    X509 * x509 = X509_new();
    if(!x509)
    {
        return NULL;
    }
    
    /* Set the serial number. */
    ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);
    
    /* This certificate is valid from now until exactly one year from now. */
    X509_gmtime_adj(X509_get_notBefore(x509), 0);
    X509_gmtime_adj(X509_get_notAfter(x509), 31536000L);
    
    /* Set the public key for our certificate. */
    X509_set_pubkey(x509, pkey);
    
    /* We want to copy the subject name to the issuer name. */
    X509_NAME * name = X509_get_subject_name(x509);
    
    /* Set the country code and common name. */
    X509_NAME_add_entry_by_txt(name, "C",  MBSTRING_ASC, (unsigned char *)"CA",        -1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "O",  MBSTRING_ASC, (unsigned char *)"MyCompany", -1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *)"localhost", -1, -1, 0);
    
    /* Now set the issuer name. */
    X509_set_issuer_name(x509, name);
    
    /* Actually sign the certificate with our key. */
    if(!X509_sign(x509, pkey, EVP_sha256()))
    {
        X509_free(x509);
        return NULL;
    }
    
    return x509;
}

bool write_to_stdout(EVP_PKEY * pkey, X509 * x509)
{
    /* Write the key to disk. */
    bool ret = PEM_write_PrivateKey(stdout, pkey, NULL, NULL, 0, NULL, NULL);
    
    if(!ret)
    {
        return false;
    }
    
    /* Write the certificate to disk. */
    ret = PEM_write_X509(stdout, x509);
    
    if(!ret)
    {
        return false;
    }
    
    return true;
}


int doTest(void)
{
    /* Generate the key. */
    std::cout << "Generating RSA key..." << std::endl;
    
    EVP_PKEY * pkey = generate_key(2048);
    if(!pkey)
        return 1;
    
    /* Generate the certificate. */
    std::cout << "Generating x509 certificate..." << std::endl;
    
    X509 * x509 = generate_x509(pkey);
    if(!x509)
    {
        EVP_PKEY_free(pkey);
        return 1;
    }
    
    /* Write the private key and certificate out to disk. */
    std::cout << "Writing key and certificate to stdout..." << std::endl;
    
    bool ret = write_to_stdout(pkey, x509);
    EVP_PKEY_free(pkey);
    X509_free(x509);
    
    if(ret)
    {
        std::cout << "Success!" << std::endl;
        return 0;
    }
    else
        return 1;
}

 

Makefile

all: hello.html

hello.html: hello.cpp ssl.cpp
	emcc -L./openssl-1.1.0h -I./openssl-1.1.0h/include hello.cpp ssl.cpp -s WASM=1 -o hello.html -lssl -lcrypto --emrun

clean:
	rm hello.html hello.wasm hello.js 

 

Mit make lässt sich das compilieren, dabei entsteht unter Anderem eine Datei hello.html, die man mit einem aktuellen Browser ansehen kann.