libagentcrypt: A library for symmetric encryption with SSH Agent

libagentcrypt 1.0.6

A library for symmetric encryption with SSH Agent

### Copyright (c) 2019-2022, Nicola Di Lieto nicol.nosp@m.a.di.nosp@m.lieto.nosp@m.@gma.nosp@m.il.co.nosp@m.m

Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

# Introduction

libagentcrypt allows using the keys in the SSH Agent to perform symmetric, authenticated encryption and decryption securely without typing passwords. It works with both RSA and ED25519 SSH keys including those made available to a remote host by SSH Agent forwarding. The library is based on strong encryption routines from libsodium. The source code is maintained on github.

# Algorithms

The SSH Agent protocol only allows the use of ssh keys for signing data. Therefore libagentcrypt performs the following process for every symmetric encryption (agc_encrypt() function):

- pad the cleartext with random data to a size multiple of the padding size (to hide true message length) and concatenate the original length at the end of the cleartext
- generate a random hash key
- create a nonce by hashing the padded cleartext with the random hash key
- create a challenge by concatenating nonce and ssh key fingerprint
- submit the challenge to the SSH Agent for signing with the ssh key
- compute the symmetric key by hashing the agent signature data
- encrypt and authenticate the padded cleartext with the nonce and the symmetric key (using libsodium's crypto_secretbox algorithm)
- output the challenge and ciphertext

The decryption process (agc_decrypt() function) is the reverse:

- read the challenge and the ciphertext
- submit the challenge to the SSH agent for signing
- compute the symmetric key by hashing the agent signature data
- decrypt and verify the ciphertext
- read the original length at the end of the decrypted data and strip the padding bytes
- output the cleartext

Both agc_encrypt() and agc_decrypt() are intended to encrypt short blocks of data stored in memory. Two additional functions are also provided to encrypt and decrypt files of arbitrary length: agc_fencrypt() generates a random key, encrypts it with agc_encrypt() and stores it at the beginning of the output; it then uses the random key to encrypt the file with libsodium's crypto_secretstream algorithm. agc_fdecrypt() later reconstructs the key with agc_decrypt() and can then decrypt the file.

Two helper functions (agc_from_b64() and agc_to_b64()) are included to encode and decode binary data to/from base64 format. These are very useful when encrypted data must be stored in text/configuration files.

## Installation

    export PKG_URL=https://github.com/ndilieto/libagentcrypt/archive/upstream/latest.tar.gz
    mkdir -p libagentcrypt
    wget -O - $PKG_URL | tar zx -C libagentcrypt --strip-components=1
    cd libagentcrypt
    ./configure --disable-maintainer-mode
    make install

## Usage

SSH currently supports four types of keys:

- ED25519
- RSA
- DSA
- ECDSA

Signatures made by the first two (ED25519 and RSA) are deterministic, i.e. repeatedly signing the same block of input data always produces the same result. This is not true for DSA and ECDSA keys, therefore libagentcrypt cannot possibly function with these - it would still encrypt but of course the symmetric key would never be able to be recovered. The encryption functions in libagentcrypt check the key type and fail if it it is not one of RSA or ED25519. Fortunately DSA is obsolete and ECDSA may even have a NSA backdoor... RSA is still secure as long as the key size is at least 2048. For best security ED25519 keys are recommended.

The agentcrypt command line utility shows how to use the library.

# API Information

## Headers

To use libagentcrypt functions in your code you should include the libagentcrypt.h header, i.e.

#include <libagentcrypt.h>

## Namespace

All identifiers defined by the libagentcrypt.h header use the prefix agc_

## Functions

The following functions are provided by the library:

- agc_encrypt()
- agc_decrypt()
- agc_fencrypt()
- agc_fdecrypt()
- agc_from_b64()
- agc_to_b64()
- agc_free()