# jnsphttps://blog.pinterjann.is/2019-09-28T13:37:00+02:00Information Security, Software Development and *NIXUse a smart card for WiFi authentication on Linux2019-09-28T13:37:00+02:002019-09-28T13:37:00+02:00Jannis Pintertag:blog.pinterjann.is,2019-09-28:/smartcard-eap-tls-wifi-linux.html<p class="first last">Smart cards can store and generate cryptographic keys in a way that makes it difficult to extract or copy them by malware or adversaries. Thus, smart cards are ideal to store keys for authentication and digital signatures. Why not just use one to authenticate against your home WiFi network?</p>
<p>Smart cards can store and generate cryptographic keys in a way that makes it difficult to extract or copy them by malware or adversaries. Thus, smart cards are ideal to store keys for authentication and digital signatures. Why not just use one to authenticate against your home WiFi network?</p>
<p>I just enrolled for a masters programme at Ruhr-University Bochum which issues smart cards to their students and staff. The smart card already holds an authentication certificate and additionally a signature certificate, both use 2048 bit RSA key pairs. Since I use the card all day for various authentication and signature tasks, it occupies my built-in smart card reader slot all the time.</p>
<p>I wanted to use the card to authenticate against my home wifi network with a TLS client certificate issued by my own PKI. So I created a key pair on the card and issued a new TLS client authentication certificate using that key. I then had a valid certificate on the filesystem with the corresponding private key on the smart card. Excellent.</p>
<div class="section" id="setting-it-up-step-by-step">
<h2>Setting it up: Step-by-step</h2>
<p>You might wind up in a situation where you have to use a smart card to connect to a Wifi network. While this should work out-of-the-box on Microsoft Windows, it isn't really straight forward to do so on a Linux machine. Documenation about how to properly configure wpa_supplicant or netctl with smart cards is scarce and almost never fully covers your use case. I will briefly explain the steps required to get your smart card to work with wpa_supplicant and give you a few hints and references to documentation that might help you in your specific use case.</p>
<div class="section" id="step-1-make-sure-your-smart-card-and-your-reader-work-as-intended">
<h3>Step 1: Make sure your smart card and your reader work as intended</h3>
<p>Make sure your smart card reader is detected by the OS, that <cite>pcscd</cite> is running and search for new cards with <cite>pcsc_scan</cite>. If that fails, consult the documentation on smart cards for your distribution.</p>
<ul class="simple">
<li>Arch Linux: <a class="reference external" href="https://wiki.archlinux.org/index.php/Smartcards">https://wiki.archlinux.org/index.php/Smartcards</a></li>
<li>Debian: <a class="reference external" href="https://wiki.debian.org/Smartcards">https://wiki.debian.org/Smartcards</a></li>
<li>RHEL: <a class="reference external" href="https://access.redhat.com/articles/3034441">https://access.redhat.com/articles/3034441</a></li>
</ul>
</div>
<div class="section" id="step-2-get-to-know-the-id-of-the-key-you-want-to-use-on-the-card">
<h3>Step 2: Get to know the id of the key you want to use on the card</h3>
<p>You can store multiple key pairs on a smart card, each is stored in a <cite>container</cite> on the card which is identified by an ID. Conveniently, you can use the ID to specify which key you want to use on the card.</p>
<p>You can simply run <cite>pkcs15-tool -k</cite> to list all the private keys present on your token.</p>
<pre class="literal-block">
$ pkcs15-tool -k
----------------------------------------------------------------
..
Private RSA Key [WIFICERT]
Object Flags : [0x3], private, modifiable
Usage : [0x6], decrypt, sign
Access Flags : [0x15], sensitive, neverExtract
ModLength : 2048
Key ref : 1 (0x1)
Native : yes
Path : 3f00501550724b23
Auth ID : 01
ID : 2087b02273594992b404743cc2b62c30
MD:guid : 03db637b-bd5d-3417-0a2a-509812b229c6
..
</pre>
<p>In my case, I want to use the key with the ID <cite>2087b02273594992b404743cc2b62c30</cite> with the object name <cite>WIFICERT</cite>. Furthermore, you can later specify the serial number of your token, so that you only use the key with ID 2087b02273594992b404743cc2b62c30 on the card with a specific serial number. This is useful if you use multiple smart cards or tokens (e.g. having both a smart card and a YubiKey plugged in). To list the serial number, display the card information with <cite>pkcs15-tool --list-info</cite>.</p>
<pre class="literal-block">
$ pkcs15-tool --list-info
----------------------------------------------------------------
PKCS#15 Card [Student Card]:
Version : 0
Serial number : 02086AE900000000
Manufacturer ID: cv cryptovision gmbh (c) v1.1n
Flags : Login required, PRN generation, EID compliant
</pre>
</div>
<div class="section" id="step-3-configure-wpa-supplicant-accordingly">
<h3>Step 3: Configure wpa_supplicant accordingly</h3>
<p>Instead of file paths, you can feed the <cite>client_cert</cite> and <cite>private_key</cite> options with <a class="reference external" href="https://tools.ietf.org/html/rfc7512">PKCS#11 URIs</a> to locate a specific key on a smart card or token. Additionally, you have to specify the <cite>pkcs11_engine_path</cite> and the <cite>pkcs11_module_path</cite> with PKCS#11 engines and modules that were built against your version of OpenSSL.</p>
<p>Hint: On Arch Linux, you might need the package <a class="reference external" href="https://www.archlinux.org/packages/community/x86_64/libp11/">libp11</a> so that OpenSSL can find the correct PKCS#11 engine. You can test this with <cite>openssl engine pkcs11</cite>. If that OpenSSL command fails, try to fix that first. It should return something like <cite>(pkcs11) pkcs11 engine</cite> when everything is good.</p>
<pre class="literal-block">
ctrl_interface=/run/wpa_supplicant
ctrl_interface_group=wheel
pkcs11_engine_path=/usr/lib/pkcs11/opensc-pkcs11.so
pkcs11_module_path=/usr/lib/opensc-pkcs11.so
network={
ssid="Free wireless charging 🔌"
key_mgmt=WPA-EAP
proto=WPA2
eap=TLS
identity="Your idendity (typically CN)"
client_cert="/path/to/certificate.pem"
private_key="pkcs11:object="WIFICERT";serial=02086AE900000000;id=%2087b02273594992b404743cc2b62c30?pin-value=XXXXXX"
ca_cert="/path/to/ca-certificate.pem"
domain_match="hostname.of.radius.server.com"
}
</pre>
<p>Note the <cite>private_key</cite> line above. Instead of supplying a path to a key file on the filesystem, we provide a PKCS#11 URI to locate the private key on the smart card. You can do a similar thing with <cite>client_cert</cite> or <cite>ca_cert</cite> to also load the certificates from the card. The user PIN has to be stored in plain text within the wpa_supplicant configuration file. I could not find a better solution that protects the PIN in responsible way, thus make sure that the access permissions to the configuration file are sufficiently strict.</p>
</div>
<div class="section" id="step-4-connect">
<h3>Step 4: Connect</h3>
<p>Running wpa_supplicant directly can be extremly helpful.</p>
<pre class="literal-block">
# wpa_supplicant -i wlp1s0 -c /etc/wpa_supplicant/smartcard_network.conf
</pre>
<p>Later on you might want to use something like netctl as a wrapper around wpa_supplicant to handle things like DHCP, DNS or certain hook scripts you like to run when you connect to a network.</p>
<pre class="literal-block">
$ cat /etc/netctl/wlan-wpa-config
----------------------------------------------------------------
Interface=wlp1s0
Connection=wireless
Security=wpa-config
IP=dhcp
IP6=stateless
WPAConfigFile='/etc/wpa_supplicant/smartcard_network.conf'
</pre>
</div>
</div>
Prefer ChaCha20-Poly1305 in TLS 1.3 with nginx2019-05-01T13:37:00+02:002019-05-01T13:37:00+02:00Jannis Pintertag:blog.pinterjann.is,2019-05-01:/chacha20-tls13-openssl.html<p class="first last">TLS 1.3 defines a new format for cipher suites that is incompatible with previous versions of the protocol. Unfortunately, many applications today do not allow to specify the order of preference for those new cipher suites which leads to the default set by the underlying TLS library (which often happens to be OpenSSL).</p>
<p>TLS 1.3 defines a new format for cipher suites that is incompatible with previous versions of the protocol. Unfortunately, many applications today do not allow to specify the order of preference for those new cipher suites which leads to the default set by the underlying TLS library (which often happens to be OpenSSL).</p>
<p>Even though you cannot change the server-side preference for TLS 1.3 cipher suites within your application, you can change the defaults used by OpenSSL. In this blog post, I will briefly explain how to change the order of preference for TLS 1.3 cipher suites with OpenSSL and nginx. This method should also work for many other applications, such as Apache or Postfix, that utilize the default settings of OpenSSL.</p>
<div class="section" id="edit-openssl-configuration-file">
<h2>Edit OpenSSL configuration file</h2>
<p>On a typical Linux system, the configuration file for OpenSSL is located in /etc/ssl/openssl.cnf. Open it with your favorite text editor and add the following lines to the top of the file.</p>
<pre class="literal-block">
openssl_conf = default_conf
[default_conf]
ssl_conf = ssl_sect
[ssl_sect]
system_default = system_default_sect
[system_default_sect]
Ciphersuites = TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384
Options = ServerPreference
</pre>
<p>The <cite>Ciphersuites</cite> option defines the default cipher suites used in TLS 1.3. You can adapt the order here to suit your needs. Keep in mind that you should at least offer <cite>TLS_AES_128_GCM_SHA256</cite> to stay compliant with <a class="reference external" href="https://tools.ietf.org/html/rfc8446#section-9.1">RFC 8446 section 9.1</a>.
Save the changes to the file and finally restart your application (e.g. nginx). When a client negotiates TLS 1.3 with your server, the new preference will be used.</p>
<p>You can find more information on this topic <a class="reference external" href="https://trac.nginx.org/nginx/ticket/1529">here</a>.</p>
</div>
Create ED25519 certificates for TLS with OpenSSL2019-03-31T13:37:00+02:002019-03-31T13:37:00+02:00Jannis Pintertag:blog.pinterjann.is,2019-03-31:/ed25519-certificates.html<p class="first last">Algorithms designed by Daniel J. Bernstein et al. are currenlty quite popular and were implemented by many applications. X25519 is now the most widely used key exchange mechanism in TLS 1.3 and the curve has been adopted by software packages such as OpenSSH, Signal and <a class="reference external" href="https://ianix.com/pub/ed25519-deployment.html">many more</a>. Although ECC is a currently a thing in X.509 / WebPKI, the list of available curves is mostly limited to NIST's P-256, P-384 and P-521 curves. This is because the CA/Browser Forum, an industry consortium of browser vendors and public trust centers, defines only those curves as permitted in their <a class="reference external" href="https://cabforum.org/baseline-requirements-documents/">Baseline Requirements</a>. The Baseline Requirements are a set of rules for public trust centers, it is important for the CAs to follow those rules closely, otherwhise they get kicked out of the major root programms and their certificates would no longer be trusted by major browsers. However, private CAs are not subject to those rules and are free to choose whichever curve they want for their certificates.</p>
<p>Algorithms designed by Daniel J. Bernstein et al. are currenlty quite popular and were implemented by many applications. X25519 is now the most widely used key exchange mechanism in TLS 1.3 and the curve has been adopted by software packages such as OpenSSH, Signal and <a class="reference external" href="https://ianix.com/pub/ed25519-deployment.html">many more</a>.</p>
<p>Although ECC is a currently a thing in X.509 / WebPKI, the list of available curves is mostly limited to NIST's P-256, P-384 and P-521 curves. This is because the CA/Browser Forum, an industry consortium of browser vendors and public trust centers, defines only those curves as permitted in their <a class="reference external" href="https://cabforum.org/baseline-requirements-documents/">Baseline Requirements</a>. The Baseline Requirements are a set of rules for public trust centers, it is important for the CAs to follow those rules closely, otherwhise they get kicked out of the major root programs and their certificates would no longer be trusted by major browsers. However, private CAs are not subject to those rules and are free to choose whichever curve they want for their certificates.</p>
<p>Since the Snowden revelations in 2013, we know that the NSA has actively manipulated cryptographic standards to incorporate <a class="reference external" href="https://en.wikipedia.org/wiki/Dual_EC_DRBG#Weakness:_a_potential_backdoor">backdoors in crypto algorithms</a>. Since then, cryptographers raised concerns against the NIST curves, mainly because some parameters were chosen without any explanation and due to the fact that the curves were designed by the NSA. Wouldn't it be nice to use ECC with safe curves that everyone trusts?</p>
<p>Fortunately, that is indeed possible. Besides the NIST curves, there are several named curves from different standardization bodies available to choose from. In case you are using OpenSSL, you can output a list of supported curves using the following command:</p>
<p><tt class="docutils literal">$ openssl ecparam <span class="pre">-list_curves</span></tt></p>
<p>You might notice that the command won't list any of Bernstein's curves, this is due to the fact that the implementation of ED25519 and ED448 in OpenSSL works slightly different than for other named curves. I won't go into the details here, but both ED25519 and ED448 are supported in OpenSSL 1.1.1 and later versions.</p>
<div class="section" id="generate-a-ed25519-csr">
<h2>Generate a ED25519 CSR</h2>
<p>Alright, let's create a TLS certificate with one of Bernstein's safe curves. We can generate a X.509 certificate using ED25519 (or ED448) as our public-key algorithm by first computing the private key:</p>
<p><tt class="docutils literal">$ openssl genpkey <span class="pre">-algorithm</span> ED25519 > example.com.key</tt></p>
<p>Then we should create a configuration file for OpenSSL, where we can list all the SANs we want to include in the certificate as well as setting proper key usage bits:</p>
<pre class="literal-block">
$ cat openssl-25519.cnf
---------------------------------------------------------------
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
[req_distinguished_name]
C = DE
CN = www.example.com
[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = www.example.com
DNS.2 = example.com
</pre>
<p>Afterwards we can create a PKCS#10 (Certificate Signing Request) using the private key and the configuration file:</p>
<pre class="literal-block">
$ openssl req -new -out example.com.csr -key example.com.key -config openssl-25519.cnf
</pre>
<p>In my case, the CSR file looks like this:</p>
<pre class="literal-block">
-----BEGIN CERTIFICATE REQUEST-----
MIIBAzCBtgIBADAnMQswCQYDVQQGEwJERTEYMBYGA1UEAwwPd3d3LmV4YW1wbGUu
Y29tMCowBQYDK2VwAyEAK87g0b8CC1eA5mvKXt9uezZwJYWEyg74Y0xTZEkqCcyg
XDBaBgkqhkiG9w0BCQ4xTTBLMAsGA1UdDwQEAwIEMDATBgNVHSUEDDAKBggrBgEF
BQcDATAnBgNVHREEIDAegg93d3cuZXhhbXBsZS5jb22CC2V4YW1wbGUuY29tMAUG
AytlcANBAHSBX9+RjKgO3MjD72nHdiqmPdotBqF2+0mMxQB2sB3Z9WOCF1M+UvFd
JyTsMetxAQZ2UEYMCqo84oG2CWn6gAY=
-----END CERTIFICATE REQUEST-----
</pre>
<p>Fortunately, OpenSSL can decode the base64 encoded ASN.1 data structure and output it in a human readable form with the following command:</p>
<pre class="literal-block">
$ openssl req -in example.com.csr -text -noout
---------------------------------------------------------------
Certificate Request:
Data:
Version: 1 (0x0)
Subject: C = DE, CN = www.example.com
Subject Public Key Info:
Public Key Algorithm: ED25519
ED25519 Public-Key:
pub:
2b:ce:e0:d1:bf:02:0b:57:80:e6:6b:ca:5e:df:6e:
7b:36:70:25:85:84:ca:0e:f8:63:4c:53:64:49:2a:
09:cc
Attributes:
Requested Extensions:
X509v3 Key Usage:
Key Encipherment, Data Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Alternative Name:
DNS:www.example.com, DNS:example.com
Signature Algorithm: ED25519
74:81:5f:df:91:8c:a8:0e:dc:c8:c3:ef:69:c7:76:2a:a6:3d:
da:2d:06:a1:76:fb:49:8c:c5:00:76:b0:1d:d9:f5:63:82:17:
53:3e:52:f1:5d:27:24:ec:31:eb:71:01:06:76:50:46:0c:0a:
aa:3c:e2:81:b6:09:69:fa:80:06
</pre>
<p>Looks good, we successfully created a PKCS#10 CSR with OpenSSL! Now let's get it signed by our CA so we can use it with TLS.</p>
<p><strong>Hint:</strong> This obviously won't work with publicly trusted CAs such as Digicert, Sectigo or Let's Encrypt as they have to closely follow the rules defined by the CA/Browser Forum Baseline Requirements which currently only permit P-256, P-384 and P-521. However, when you run your own private CA for home or office use, this should work just fine.</p>
</div>
<div class="section" id="signing-the-csr">
<h2>Signing the CSR</h2>
<p>For this blog post, we will just issue a self signed certifcate. You can do this with OpenSSL like this:</p>
<pre class="literal-block">
$ openssl x509 -req -days 700 -in example.com.csr -signkey example.com.key -out example.com.crt
</pre>
<p>The command will issue a self signed certificate which is valid for 700 days. In my case, the issued certificate looks like this:</p>
<pre class="literal-block">
-----BEGIN CERTIFICATE-----
MIIBCDCBuwIUGW78zw0OL0GptJi++a91dBa7DsQwBQYDK2VwMCcxCzAJBgNVBAYT
AkRFMRgwFgYDVQQDDA93d3cuZXhhbXBsZS5jb20wHhcNMTkwMzMxMTc1MTIyWhcN
MjEwMjI4MTc1MTIyWjAnMQswCQYDVQQGEwJERTEYMBYGA1UEAwwPd3d3LmV4YW1w
bGUuY29tMCowBQYDK2VwAyEAK87g0b8CC1eA5mvKXt9uezZwJYWEyg74Y0xTZEkq
CcwwBQYDK2VwA0EAIIu/aa3Qtr3IE5to/nvWVY9y3ciwG5DnA70X3ALUhFs+U5aL
tfY8sNT1Ng72ht+UBwByuze20UsL9qMsmknQCA==
-----END CERTIFICATE-----
</pre>
<p>As with the CSR previously, we can use OpenSSL to pretty-print the information from the certificate:</p>
<pre class="literal-block">
$ openssl x509 -in example.com.crt -text -noout
---------------------------------------------------------------
Certificate:
Data:
Version: 1 (0x0)
Serial Number:
19:6e:fc:cf:0d:0e:2f:41:a9:b4:98:be:f9:af:75:74:16:bb:0e:c4
Signature Algorithm: ED25519
Issuer: C = DE, CN = www.example.com
Validity
Not Before: Mar 31 17:51:22 2019 GMT
Not After : Feb 28 17:51:22 2021 GMT
Subject: C = DE, CN = www.example.com
Subject Public Key Info:
Public Key Algorithm: ED25519
ED25519 Public-Key:
pub:
2b:ce:e0:d1:bf:02:0b:57:80:e6:6b:ca:5e:df:6e:
7b:36:70:25:85:84:ca:0e:f8:63:4c:53:64:49:2a:
09:cc
Signature Algorithm: ED25519
20:8b:bf:69:ad:d0:b6:bd:c8:13:9b:68:fe:7b:d6:55:8f:72:
dd:c8:b0:1b:90:e7:03:bd:17:dc:02:d4:84:5b:3e:53:96:8b:
b5:f6:3c:b0:d4:f5:36:0e:f6:86:df:94:07:00:72:bb:37:b6:
d1:4b:0b:f6:a3:2c:9a:49:d0:08
</pre>
<p>We can now use the certificate with our favorite webserver. If it was built against a recent OpenSSL release, it should be able to work with the certificate just fine.</p>
<p>Unfortunately, none of the major browsers seem to support ED25519 based certificates for TLS as of now. We can however use OpenSSL itself to test the connection and verify that it actually works.</p>
<pre class="literal-block">
$ openssl s_client -connect example.com:443
</pre>
</div>
Reboot2018-11-05T13:37:00+01:002018-11-05T13:37:00+01:00Jannis Pintertag:blog.pinterjann.is,2018-11-05:/reboot-01.html<p class="first last">This blog has not received much attention in the few years of its existence. Today I decieded to give it a reboot and start over, only keeping the articles that I felt were most interessting. I changed the layout a bit and switched to pelican, a static site generator, to manage this site. The focus of this blog lies on information security, specifically on everything that is related to TLS and the PKI ecosystem. However, there may be traces of software development and unix on this blog.</p>
<p>This blog has not received much attention in the few years of its existence. Today I decieded to give it a reboot and start over, only keeping the articles that I felt were most interessting. I changed the layout a bit and switched to pelican, a static site generator, to manage this site.</p>
<p>The focus of this blog lies on information security, specifically on everything that is related to TLS and the PKI ecosystem. However, there may be traces of software development and unix on this blog.</p>
TLS 1.32018-05-28T13:37:00+02:002018-05-28T13:37:00+02:00Jannis Pintertag:blog.pinterjann.is,2018-05-28:/tls13-01.html<p class="first last">TLS 1.3 is around the corner, the new protocol is faster and more secure than its predecessors. The protocol only supports authenticated encryption, using either AES-GCM, AES-CCM or CHACHA20-POLY1305. Due to some optimizations during the handshake phase, a TLS 1.3 connection can be established within a single round trip (instead of two). Forward secrecy is now mandatory, which apparently caused problems for <a class="reference external" href="https://www.ietf.org/mail-archive/web/tls/current/msg21275.html">banks</a>, who claimed breaking into their own TLS connections is necessary for debugging and security monitoring. Currently, there are not many sites on the web that allow you to test your user agent for TLS 1.3 support. I decided to create a <a class="reference external" href="https://tls13.pinterjann.is">small website</a> that indicates whether you are connected using TLS 1.2 or TLS 1.3 and which cipher suite was negotiated.</p>
<p>TLS 1.3 is around the corner, the new protocol is faster and more secure than its predecessors. The protocol only supports authenticated encryption, using either AES-GCM, AES-CCM or CHACHA20-POLY1305. Due to some optimizations during the handshake phase, a TLS 1.3 connection can be established within a single round trip (instead of two). Forward secrecy is now mandatory, which apparently caused problems for <a class="reference external" href="https://www.ietf.org/mail-archive/web/tls/current/msg21275.html">banks</a>, who claimed breaking into their own TLS connections is necessary for debugging and security monitoring.</p>
<p>Currently, there are not many sites on the web that allow you to test your user agent for TLS 1.3 support. I decided to create a <a class="reference external" href="https://tls13.pinterjann.is">small website</a> that indicates whether you are connected using TLS 1.2 or TLS 1.3 and which cipher suite was negotiated.</p>
<p>At the time of writing, you should be able to connect using TLS 1.3 with development versions of Firefox and Chrome.</p>
Launching a weather ballon, a camera and a Raspberry Pi to the stratosphere2015-05-06T00:00:00+02:002015-05-06T00:00:00+02:00Jannis Pintertag:blog.pinterjann.is,2015-05-06:/stratoshpere-01.html<p class="first last">On Saturday 14th February, two of my classmates and I launched a weather ballon. We’ve got some amazing video footage from the black forest to the stratosphere. Furthermore, we’ve collected temperature, humidity, ultraviolet light and air pressure data with several sensors connected to a Raspberry Pi.</p>
<p>On Saturday 14th February, two of my classmates and I launched a weather ballon. We’ve got some amazing video footage from the black forest to the stratosphere. Furthermore, we’ve collected temperature, humidity, ultraviolet light and air pressure data with several sensors connected to a Raspberry Pi.</p>
<div class="centralize figure align-center">
<a class="reference external image-reference" href="https://blog.pinterjann.is/img/stratosphere/stratosphere.jpg"><img alt="Stratosphere at around 30,000 meters above earth" src="https://blog.pinterjann.is/img/stratosphere/stratosphere.jpg" style="width: 400px;" /></a>
<p class="caption">Stratosphere at around 30,000 meters above earth.</p>
</div>
<div class="section" id="the-probe">
<h2>The probe</h2>
<p>The probe that housed all the measuring instruments and the camera was built out of styrofoamâ„¢ and lots of duck tape. Basically, we built a box with three chambers. One for the camera, another one for the Raspberry Pi and the last one for the batteries. The most important thing is to use really good cords to attach the parachute and the box to the ballon. Otherwise, the cords might just rip apart.</p>
<div class="gallery docutils container">
<div class="centralize figure align-center">
<a class="reference external image-reference" href="https://blog.pinterjann.is/img/stratosphere/debugging_the_pi.jpg"><img alt="Debugging" src="https://blog.pinterjann.is/img/stratosphere/debugging_the_pi.jpg" style="width: 200px;" /></a>
<p class="caption">Debugging</p>
</div>
<div class="centralize figure align-center">
<a class="reference external image-reference" href="https://blog.pinterjann.is/img/stratosphere/assembling_the_probe.jpg"><img alt="Assembling" src="https://blog.pinterjann.is/img/stratosphere/assembling_the_probe.jpg" style="width: 200px;" /></a>
<p class="caption">Assembling</p>
</div>
</div>
</div>
<div class="section" id="launch-site">
<h2>Launch site</h2>
<p>We launched our ballon on a sports field in <a class="reference external" href="http://www.openstreetmap.org/?mlat=48.5864&mlon=8.1041#map=14/48.5864/8.1041">Kappelrodeck</a>, a small town in Germany. The weather was cold and there was still some snow left on the ground. After we prepared everything, we started to fill the ballon with helium and powered up our measuring instruments. At around 11:15am, the balloon was ready to go and we let it fly.</p>
<p>We immediately realized, that our probe weighed a bit too much, so the ballon went up much slower than we initially thought. However, the ballon took just two more hours than planed to reach the stratosphere, so we’d still call it a success.</p>
</div>
<div class="section" id="the-flight">
<h2>The flight</h2>
<p>Based on our sensor data, we can say that the overall flight took about 5 hours. The ballon reached it’s peak height of around 31,000 meters after 4 hours and 30 minutes, before it bursted and everything fell down to earth again.</p>
<p>Unfortunately, the memory card in the camera was full after 4 hours and 50 minutes. So the last 20 minutes of the landing could not be captured.</p>
<div class="gallery docutils container">
<div class="centralize figure align-center">
<a class="reference external image-reference" href="https://blog.pinterjann.is/img/stratosphere/shortly_after_launch.jpg"><img alt="Shortly after launch" src="https://blog.pinterjann.is/img/stratosphere/shortly_after_launch.jpg" style="width: 200px;" /></a>
<p class="caption">Shortly after launch</p>
</div>
<div class="centralize figure align-center">
<a class="reference external image-reference" href="https://blog.pinterjann.is/img/stratosphere/foggy_black_forest.jpg"><img alt="Foggy Black Forest" src="https://blog.pinterjann.is/img/stratosphere/foggy_black_forest.jpg" style="width: 200px;" /></a>
<p class="caption">Foggy Black Forest</p>
</div>
<div class="centralize figure align-center">
<a class="reference external image-reference" href="https://blog.pinterjann.is/img/stratosphere/black_forest_panorama.jpg"><img alt="Black Forest panorama" src="https://blog.pinterjann.is/img/stratosphere/black_forest_panorama.jpg" style="width: 200px;" /></a>
<p class="caption">Black Forest panorama</p>
</div>
</div>
<div class="gallery docutils container">
<div class="centralize figure align-center">
<a class="reference external image-reference" href="https://blog.pinterjann.is/img/stratosphere/blue_sky_above_the_clouds.jpg"><img alt="Above the clouds" src="https://blog.pinterjann.is/img/stratosphere/blue_sky_above_the_clouds.jpg" style="width: 200px;" /></a>
<p class="caption">Above the clouds</p>
</div>
<div class="centralize figure align-center">
<a class="reference external image-reference" href="https://blog.pinterjann.is/img/stratosphere/stratosphere.jpg"><img alt="Stratosphere at around 30,000m" src="https://blog.pinterjann.is/img/stratosphere/stratosphere.jpg" style="width: 200px;" /></a>
<p class="caption">At around 30,000m</p>
</div>
<div class="centralize figure align-center">
<a class="reference external image-reference" href="https://blog.pinterjann.is/img/stratosphere/ballon_bursts.jpg"><img alt="At around 31,000 meters, the ballon bursted" src="https://blog.pinterjann.is/img/stratosphere/ballon_bursts.jpg" style="width: 200px;" /></a>
<p class="caption">The ballon bursted</p>
</div>
</div>
</div>
<div class="section" id="landing-and-recovery">
<h2>Landing and recovery</h2>
<p>After a successful flight, the probe landed around 150km further north, in Wald-Michelbach, Hesse, Germany. After we’ve got a signal from the GPS tracker, we immediatly drove their to retrieve the probe. Unfortunately, the probe and the parachute hung in the trees in around 20m height. The local authorities helped us a lot, the forester aranged the cutting of two trees for us, because it was nearly impossible to get the probe down in any other way.</p>
<div class="gallery docutils container">
<div class="centralize figure align-center">
<a class="reference external image-reference" href="https://blog.pinterjann.is/img/stratosphere/probe_in_the_trees.jpg"><img alt="The probe hung in 20m" src="https://blog.pinterjann.is/img/stratosphere/probe_in_the_trees.jpg" style="width: 200px;" /></a>
<p class="caption">The probe in the trees</p>
</div>
</div>
</div>
<div class="section" id="analysis-of-the-recorded-data">
<h2>Analysis of the recorded data</h2>
<p>Our software recorded several 100,000 datasets during the flight. The data is encoded in JSON, that allows us to use the data in very flexible ways – altough it adds a little overhead compared to a CSV format. In the end, we had a little more than 10 megabytes of JSON encoded sensor data and 32 gigabytes of video footage.</p>
<p>You can check out the raw results <a class="reference external" href="https://io.pinterjann.is/public/schule/BKFH/projekt/messdaten/">here</a>.</p>
</div>
<div class="section" id="video-recording">
<h2>Video recording</h2>
<p>Either watch the edited video on <a class="reference external" href="https://www.youtube.com/watch?v=szZBzbF34eI">YouTube</a> or the unedited video in <a class="reference external" href="https://io.pinterjann.is/public/schule/BKFH/projekt/flug.webm">full length</a>.</p>
</div>