300 lines
20 KiB
HTML
300 lines
20 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8"/>
|
|
<style>
|
|
table.head, table.foot { width: 100%; }
|
|
td.head-rtitle, td.foot-os { text-align: right; }
|
|
td.head-vol { text-align: center; }
|
|
div.Pp { margin: 1ex 0ex; }
|
|
</style>
|
|
<link rel="stylesheet" href="style.css" type="text/css" media="all"/>
|
|
<title>INTRO(3MONOCYPHER)</title>
|
|
</head>
|
|
<body>
|
|
<table class="head">
|
|
<tr>
|
|
<td class="head-ltitle">INTRO(3MONOCYPHER)</td>
|
|
<td class="head-vol">3MONOCYPHER</td>
|
|
<td class="head-rtitle">INTRO(3MONOCYPHER)</td>
|
|
</tr>
|
|
</table>
|
|
<div class="manual-text">
|
|
<h1 class="Sh" title="Sh" id="NAME"><a class="selflink" href="#NAME">NAME</a></h1>
|
|
<b class="Nm" title="Nm">intro</b> —
|
|
<span class="Nd" title="Nd">introduction to Monocypher</span>
|
|
<h1 class="Sh" title="Sh" id="DESCRIPTION"><a class="selflink" href="#DESCRIPTION">DESCRIPTION</a></h1>
|
|
Monocypher is a cryptographic library. It provides functions for authenticated
|
|
encryption, hashing, password hashing and key derivation, key exchange, and
|
|
public key signatures.
|
|
<h2 class="Ss" title="Ss" id="Authenticated_encryption"><a class="selflink" href="#Authenticated_encryption">Authenticated
|
|
encryption</a></h2>
|
|
<a class="Xr" title="Xr" href="crypto_lock.html">crypto_lock(3monocypher)</a>
|
|
and
|
|
<a class="Xr" title="Xr" href="crypto_unlock.html">crypto_unlock(3monocypher)</a>
|
|
use the Chacha20 cipher and the Poly1305 one-time authenticator.
|
|
<div class="Pp"></div>
|
|
Chacha20 is a stream cipher based on a cryptographic hash function. It runs
|
|
efficiently on a wide variety of hardware, and unlike AES naturally runs in
|
|
constant time on all hardware.
|
|
<div class="Pp"></div>
|
|
Poly1305 is a one-time authenticator, derived from Carter & Wegman universal
|
|
hashing. It is very fast and very simple.
|
|
<div class="Pp"></div>
|
|
For specialised needs,
|
|
<a class="Xr" title="Xr" href="crypto_chacha20.html">crypto_chacha20(3monocypher)</a>
|
|
and
|
|
<a class="Xr" title="Xr" href="crypto_poly1305.html">crypto_poly1305(3monocypher)</a>
|
|
are available to implement constructions involving them. Whenever possible,
|
|
<a class="Xr" title="Xr" href="crypto_lock.html">crypto_lock(3monocypher)</a>
|
|
should be preferred, however.
|
|
<h2 class="Ss" title="Ss" id="Hashing"><a class="selflink" href="#Hashing">Hashing</a></h2>
|
|
<a class="Xr" title="Xr" href="crypto_blake2b.html">crypto_blake2b(3monocypher)</a>
|
|
implements the Blake2b hash. Blake2b combines the security of SHA-3 and the
|
|
speed of MD5. It is immune to length extension attacks and provides a keyed
|
|
mode that makes it a safe, easy to use authenticator.
|
|
<h2 class="Ss" title="Ss" id="Password_hashing_and_key_derivation"><a class="selflink" href="#Password_hashing_and_key_derivation">Password
|
|
hashing and key derivation</a></h2>
|
|
<a class="Xr" title="Xr" href="crypto_argon2i.html">crypto_argon2i(3monocypher)</a>
|
|
implements the Argon2i resource intensive hash algorithm, which can be used to
|
|
hash passwords for storage and to derive keys from passwords. Argon2 won the
|
|
password hashing competition in 2015. Unlike Scrypt, Argon2i is immune to
|
|
timing attacks.
|
|
<h2 class="Ss" title="Ss" id="Key_exchange"><a class="selflink" href="#Key_exchange">Key
|
|
exchange</a></h2>
|
|
<a class="Xr" title="Xr" href="crypto_key_exchange.html">crypto_key_exchange(3monocypher)</a>
|
|
implements X25519, an elliptic curve Diffie Hellman key exchange algorithm
|
|
based on Curve25519. X25519 derives a shared secret from two private/public
|
|
key pairs. It is fast, simple, and relatively easy to implement securely.
|
|
<div class="Pp"></div>
|
|
For specialised protocols that require indistinguishability from random noise,
|
|
<a class="Xr" title="Xr" href="crypto_curve_to_hidden.html">crypto_curve_to_hidden(3monocypher)</a>
|
|
gives the option to disguise ephemeral (one-time use) X25519 public keys as
|
|
random noise.
|
|
<h2 class="Ss" title="Ss" id="Public_key_signatures"><a class="selflink" href="#Public_key_signatures">Public
|
|
key signatures</a></h2>
|
|
<a class="Xr" title="Xr" href="crypto_sign.html">crypto_sign(3monocypher)</a>
|
|
and
|
|
<a class="Xr" title="Xr" href="crypto_check.html">crypto_check(3monocypher)</a>
|
|
implement EdDSA, with Curve25519 and Blake2b. This is the same as the more
|
|
famous Ed25519, with SHA-512 replaced by the faster and more secure Blake2b.
|
|
<div class="Pp"></div>
|
|
For highly specialised needs, it is possible to use a custom hash function with
|
|
EdDSA; see
|
|
<a class="Xr" title="Xr" href="crypto_sign_init_first_pass_custom_hash.html">crypto_sign_init_first_pass_custom_hash(3monocypher)</a>.
|
|
<h2 class="Ss" title="Ss" id="Constant_time_comparison"><a class="selflink" href="#Constant_time_comparison">Constant
|
|
time comparison</a></h2>
|
|
<a class="Xr" title="Xr" href="crypto_verify16.html">crypto_verify16(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_verify32.html">crypto_verify32(3monocypher)</a>,
|
|
and
|
|
<a class="Xr" title="Xr" href="crypto_verify64.html">crypto_verify64(3monocypher)</a>
|
|
compare buffers in constant time. They should be used to compare secrets to
|
|
prevent timing attacks.
|
|
<h2 class="Ss" title="Ss" id="Memory_wipe"><a class="selflink" href="#Memory_wipe">Memory
|
|
wipe</a></h2>
|
|
<a class="Xr" title="Xr" href="crypto_wipe.html">crypto_wipe(3monocypher)</a>
|
|
wipes a buffer. It is meant to erase secrets when they are no longer needed,
|
|
to reduce the chances of leaks.
|
|
<h2 class="Ss" title="Ss" id="Optional_code"><a class="selflink" href="#Optional_code">Optional
|
|
code</a></h2>
|
|
If Monocypher was compiled and installed with
|
|
<code class="Dv" title="Dv">USE_ED25519</code>, SHA-512 functions become
|
|
available as well. See
|
|
<a class="Xr" title="Xr" href="crypto_ed25519_sign.html">crypto_ed25519_sign(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_ed25519_sign_init_first_pass.html">crypto_ed25519_sign_init_first_pass(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_sha512.html">crypto_sha512(3monocypher)</a>,
|
|
and
|
|
<a class="Xr" title="Xr" href="crypto_hmac_sha512.html">crypto_hmac_sha512(3monocypher)</a>.
|
|
<h1 class="Sh" title="Sh" id="SEE_ALSO"><a class="selflink" href="#SEE_ALSO">SEE
|
|
ALSO</a></h1>
|
|
<a class="Xr" title="Xr" href="crypto_argon2i.html">crypto_argon2i(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_argon2i_general.html">crypto_argon2i_general(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_blake2b.html">crypto_blake2b(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_blake2b_final.html">crypto_blake2b_final(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_blake2b_general.html">crypto_blake2b_general(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_blake2b_general_init.html">crypto_blake2b_general_init(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_blake2b_init.html">crypto_blake2b_init(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_blake2b_update.html">crypto_blake2b_update(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_chacha20.html">crypto_chacha20(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_chacha20_ctr.html">crypto_chacha20_ctr(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_check.html">crypto_check(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_check_final.html">crypto_check_final(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_check_init.html">crypto_check_init(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_check_init_custom_hash.html">crypto_check_init_custom_hash(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_check_update.html">crypto_check_update(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_curve_to_hidden.html">crypto_curve_to_hidden(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_from_eddsa_private.html">crypto_from_eddsa_private(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_from_eddsa_public.html">crypto_from_eddsa_public(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_hchacha20.html">crypto_hchacha20(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_hidden_key_pair.html">crypto_hidden_key_pair(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_hidden_to_curve.html">crypto_hidden_to_curve(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_ietf_chacha20.html">crypto_ietf_chacha20(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_ietf_chacha20_ctr.html">crypto_ietf_chacha20_ctr(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_key_exchange.html">crypto_key_exchange(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_lock.html">crypto_lock(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_lock_aead.html">crypto_lock_aead(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_poly1305.html">crypto_poly1305(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_poly1305_final.html">crypto_poly1305_final(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_poly1305_init.html">crypto_poly1305_init(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_poly1305_update.html">crypto_poly1305_update(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_sign.html">crypto_sign(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_sign_final.html">crypto_sign_final(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_sign_init_first_pass.html">crypto_sign_init_first_pass(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_sign_init_first_pass_custom_hash.html">crypto_sign_init_first_pass_custom_hash(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_sign_init_second_pass.html">crypto_sign_init_second_pass(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_sign_public_key.html">crypto_sign_public_key(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_sign_public_key_custom_hash.html">crypto_sign_public_key_custom_hash(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_sign_update.html">crypto_sign_update(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_unlock.html">crypto_unlock(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_unlock_aead.html">crypto_unlock_aead(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_verify16.html">crypto_verify16(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_verify32.html">crypto_verify32(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_verify64.html">crypto_verify64(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_wipe.html">crypto_wipe(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_x25519.html">crypto_x25519(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_x25519_dirty_fast.html">crypto_x25519_dirty_fast(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_x25519_dirty_small.html">crypto_x25519_dirty_small(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_x25519_inverse.html">crypto_x25519_inverse(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_x25519_public_key.html">crypto_x25519_public_key(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_xchacha20.html">crypto_xchacha20(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_xchacha20_ctr.html">crypto_xchacha20_ctr(3monocypher)</a>
|
|
<h2 class="Ss" title="Ss" id="Optional_code"><a class="selflink" href="#Optional_code">Optional
|
|
code</a></h2>
|
|
<a class="Xr" title="Xr" href="crypto_from_ed25519_private.html">crypto_from_ed25519_private(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_from_ed25519_public.html">crypto_from_ed25519_public(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_ed25519_check.html">crypto_ed25519_check(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_ed25519_check_init.html">crypto_ed25519_check_init(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_ed25519_check_update.html">crypto_ed25519_check_update(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_ed25519_check_final.html">crypto_ed25519_check_final(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_ed25519_public_key.html">crypto_ed25519_public_key(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_ed25519_sign.html">crypto_ed25519_sign(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_ed25519_sign_init_first_pass.html">crypto_ed25519_sign_init_first_pass(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_ed25519_sign_init_second_pass.html">crypto_ed25519_sign_init_second_pass(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_ed25519_sign_final.html">crypto_ed25519_sign_final(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_hmac_sha512.html">crypto_hmac_sha512(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_hmac_sha512_init.html">crypto_hmac_sha512_init(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_hmac_sha512_update.html">crypto_hmac_sha512_update(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_hmac_sha512_final.html">crypto_hmac_sha512_final(3monocypher)</a>
|
|
<a class="Xr" title="Xr" href="crypto_sha512.html">crypto_sha512(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_sha512_init.html">crypto_sha512_init(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_sha512_update.html">crypto_sha512_update(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_sha512_final.html">crypto_sha512_final(3monocypher)</a>
|
|
<h1 class="Sh" title="Sh" id="SECURITY_CONSIDERATIONS"><a class="selflink" href="#SECURITY_CONSIDERATIONS">SECURITY
|
|
CONSIDERATIONS</a></h1>
|
|
Using cryptography securely is difficult. Flaws that never manifest under normal
|
|
use might be exploited by a clever adversary. Cryptographic libraries are easy
|
|
to misuse. Even Monocypher allows a number of fatal mistakes.
|
|
<div class="Pp"></div>
|
|
Users should follow a formal introduction to cryptography. We currently
|
|
recommend the <a class="Lk" title="Lk" href="https://www.crypto101.io/">Crypto
|
|
101 online course</a>.
|
|
<h2 class="Ss" title="Ss" id="Random_number_generation"><a class="selflink" href="#Random_number_generation">Random
|
|
number generation</a></h2>
|
|
Use the facilities of your operating system. Avoid user space random number
|
|
generators. They are easy to misuse, which has lead to countless
|
|
vulnerabilities in the past. For instance, the random stream may be repeated
|
|
if one is not careful with multi-threading, and forward secrecy is lost
|
|
without proper key erasure.
|
|
<div class="Pp"></div>
|
|
Different system calls are available on different systems:
|
|
<ul class="Bl-bullet">
|
|
<li class="It-bullet">Recent versions of Linux (glibc >= 2.25, Linux >=
|
|
3.17), provide <b class="Fn" title="Fn">getrandom</b>() in
|
|
<b class="In" title="In"><<a class="In" title="In">linux/random.h</a>></b>.
|
|
Do not set any flag.</li>
|
|
<li class="It-bullet">BSD provides
|
|
<b class="Fn" title="Fn">arc4random_buf</b>() in
|
|
<b class="In" title="In"><<a class="In" title="In">stdlib.h</a>></b>
|
|
or
|
|
<b class="In" title="In"><<a class="In" title="In">bsd/stdlib.h</a>></b>.
|
|
This is easier to use than <b class="Fn" title="Fn">getrandom</b>().</li>
|
|
<li class="It-bullet">Windows provides
|
|
<b class="Fn" title="Fn">BCryptGenRandom</b>().</li>
|
|
</ul>
|
|
<div class="Pp"></div>
|
|
The <i class="Pa" title="Pa">/dev/urandom</i> special file may be used on
|
|
systems that do not provide an easy to use system call. Be careful though,
|
|
being a file makes <i class="Pa" title="Pa">/dev/urandom</i> hard to use
|
|
correctly and securely. Reads may be interrupted, and more attacks are
|
|
possible on a file than on a system call.
|
|
<h2 class="Ss" title="Ss" id="Timing_attacks"><a class="selflink" href="#Timing_attacks">Timing
|
|
attacks</a></h2>
|
|
Monocypher runs in “constant time”. There is no flow from secrets
|
|
to timings. No secret dependent indices, no secret dependent branches.
|
|
Nevertheless, there are a couple important caveats.
|
|
<div class="Pp"></div>
|
|
Comparing secrets should be done with constant-time comparison functions, such
|
|
as
|
|
<a class="Xr" title="Xr" href="crypto_verify16.html">crypto_verify16(3monocypher)</a>,
|
|
<a class="Xr" title="Xr" href="crypto_verify32.html">crypto_verify32(3monocypher)</a>,
|
|
or
|
|
<a class="Xr" title="Xr" href="crypto_verify64.html">crypto_verify64(3monocypher)</a>.
|
|
Do not use standard comparison functions. They tend to stop as soon as a
|
|
difference is spotted. In many cases, this enables attackers to recover the
|
|
secrets and destroy all security.
|
|
<div class="Pp"></div>
|
|
The Poly1305 authenticator, X25519, and EdDSA use multiplication. Some older
|
|
processors do not multiply in constant time. If the target platform is
|
|
something other than Intel or AMD x86_64, double check how it handles
|
|
multiplication. In particular, <i class="Em" title="Em">ARM Cortex-M CPUs may
|
|
lack constant-time multiplication</i>. Some VIA Nano x86 and x86_64 CPUs may
|
|
lack constant-time multiplication as well.
|
|
<h2 class="Ss" title="Ss" id="Data_compression"><a class="selflink" href="#Data_compression">Data
|
|
compression</a></h2>
|
|
Encryption does not hide the length of the input plaintext. Most compression
|
|
algorithms work by using fewer bytes to encode previously seen data or common
|
|
characters. If an attacker can add data to the input before it is compressed
|
|
and encrypted, they can observe changes to the ciphertext length to recover
|
|
secrets from the input. Researchers have demonstrated an attack on HTTPS to
|
|
steal session cookies when compression is enabled, dubbed
|
|
“CRIME”.
|
|
<h2 class="Ss" title="Ss" id="Forward_secrecy"><a class="selflink" href="#Forward_secrecy">Forward
|
|
secrecy</a></h2>
|
|
Long term secrets cannot be expected to stay safe indefinitely. Users may reveal
|
|
them by mistake, or the host computer might have a vulnerability and be
|
|
compromised. To mitigate this problem, some protocols guarantee that past
|
|
messages are not compromised even if the long term keys are. This is done by
|
|
generating temporary keys, then encrypting messages using them.
|
|
<div class="Pp"></div>
|
|
In general, secrets that went through a computer should not be compromised when
|
|
this computer is stolen or infected at a later point.
|
|
<div class="Pp"></div>
|
|
A first layer of defence is to explicitly wipe secrets as soon as they are no
|
|
longer used. Monocypher already wipes its own temporary buffers, and contexts
|
|
are erased with the <b class="Fn" title="Fn">crypto_*_final</b>() functions.
|
|
The secret keys and messages however are the responsibility of the user. Use
|
|
<a class="Xr" title="Xr" href="crypto_wipe.html">crypto_wipe(3monocypher)</a>
|
|
to erase them.
|
|
<div class="Pp"></div>
|
|
A second layer of defence is to ensure those secrets are not swapped to disk
|
|
while they are used. There are several ways to do this. The most secure is to
|
|
disable swapping entirely. Doing so is recommended on sensitive machines.
|
|
Another way is to encrypt the swap partition (this is less safe). Finally,
|
|
swap can be disabled locally – this is often the only way.
|
|
<div class="Pp"></div>
|
|
UNIX systems can disable swap for specific buffers with
|
|
<b class="Fn" title="Fn">mlock</b>(), and disable swap for the whole process
|
|
with <b class="Fn" title="Fn">mlockall</b>(). Windows can disable swap for
|
|
specific buffers with <b class="Fn" title="Fn">VirtualLock</b>().
|
|
<div class="Pp"></div>
|
|
Core dumps cause similar problems. Disable them. Also beware of suspend to disk
|
|
(deep sleep mode), which writes all RAM to disk regardless of swap policy, as
|
|
well as virtual machine snapshots. Erasing secrets with
|
|
<a class="Xr" title="Xr" href="crypto_wipe.html">crypto_wipe(3monocypher)</a>
|
|
is often the only way to mitigate these dangers.
|
|
<h2 class="Ss" title="Ss" id="Undefined_behaviour"><a class="selflink" href="#Undefined_behaviour">Undefined
|
|
behaviour</a></h2>
|
|
Monocypher is a C library. C is notoriously unsafe. Using Monocypher incorrectly
|
|
can trigger undefined behaviour. This can lead to data corruption, data theft,
|
|
or even arbitrary code execution.
|
|
<div class="Pp"></div>
|
|
Consider binding to a safe language if possible.</div>
|
|
<table class="foot">
|
|
<tr>
|
|
<td class="foot-date">March 31, 2020</td>
|
|
<td class="foot-os">Linux 4.15.0-106-generic</td>
|
|
</tr>
|
|
</table>
|
|
</body>
|
|
</html>
|