blob: bb4a653511e7be616d166622f21cbfedb106d97e [file] [log] [blame] [view] [edit]
# Summary
This is a **portable crypto library** that exposes a restricted API that is
**secure by design**, for use as a black-box building block in cryptographic
protocols. Security and portability are emphasized over efficient (compact)
encodings, but keeping the crypto overhead reasonably minimal is still a
requirement. The API and implementation should encourage the use of best
practices, and reduce the likelihood of common protocol design errors.
# Overview
Existing cryptographic libraries available in most languages typically expose
raw crypto primitives (e.g., block ciphers with modes of operation, HMACs,
digital signatures) that are often applied incorrectly in protocol design.
While these libraries are "standards compliant", they do little or nothing to
guide the protocol designer to produce secure protocol designs. Worse still,
they leave ample room for implementations to introduce subtle security bugs
such as timing attacks.
The SecureMessage library leverages Google's protobuffer technology to provide
a simple and portable encoding for public keys and signed/encrypted data. The
exposed API consists of two main classes, and two supporting classes.
The main classes are:
* Secure Message Builder -- used to craft SecureMessage protos from the input
data, metadata, and keys
* Secure Message Parser -- used to extract the original input data and metadata
from a SecureMessage proto, while performing all necessary verification,
decryption, and sanity checking in a secure fashion
The supporting classes are:
* PublicKeyProtoUtil -- provides simple protobuf based encoding/decoding for
public keys (either EC or RSA), including appropriate security checks to
reject maliciously crafted inputs (e.g., EC public keys that are not on the
curve). Also assists with key generation.
* CryptoOps -- provides clean abstractions for various low-level cryptographic
operations, making it easier to port the library to new crypto providers (and
in the case of HKDF, providing clients of the library with access a portable
API for that primitive too, since it is not commonly available).
In all cases, exposed APIs are carefully thought out, in order to encourage
safe use and prevent unsafe use. For example, the SecureMessageParser API will
not return the original input data unless the signature on it has been verified
first. It also requires the caller to specify exactly which signature algorithm
is expected to be used, to prevent callers from accidentally consuming messages
sent using any other (potentially deprecated / insecure) signature algorithms.
Currently supported signature algorithms are:
* EC DSA on the NIST P-256 curve, using a SHA-256 digest (ANSI X9.62)
* 2048-bit RSA signatures using a SHA-256 digest (PKCS#1)
* HMAC with SHA-256 for "symmetric key signature" (RFC 2104)
Currently supported encryption algorithms are:
* AES-256 in CBC mode for symmetric key encryption
# Features and API
The basic API for SecureMessage consists of two classes, one of which creates
SecureMessages, whereas the other parses them. There are two basic types of
SecureMessage which these classes manipulate:
* Signed Cleartext - This is used for messages that do not require any privacy
guarantee, but which need to be authenticated. In particular, the "signature"
may be either a digital signature, or a MAC.
* Signcrypted - This is used when both privacy and authenticity are required.
The body data will first be encrypted, and then "signed". (Special measures
are taken to ensure that the original signature cannot be stripped off of the
encrypted data and replaced by another signature from a different signer.)
Note that we use the term "signature" in a generic sense, to refer to either
digital signatures (using asymmetric keys) or Message Authentication Codes
(using symmetric keys). Currently, the encryption component of signcrypted
messages only supports symmetric key encryption schemes, but this may change in
the future.
Each SecureMessage consists of two primary components: a header and a body.
The header describes the structure of the SecureMessage as well as providing a
convenient location for metadata related to the body. The body of the
SecureMessage will contain the primary payload. Rather than using the protobuf
APIs to retrieve these components from a SecureMessage, the SecureMessageParser
must be used. The header component is always sent in the clear, and can be
extracted from the SecureMessage by calling SecureMessageParser's
getUnverifiedHeader() method without the use of any cryptographic keys. Thus,
it is possible to use the header contents to determine which key(s) must be
used to verify (and possibly decrypt) the body. In order to retrieve the body
component, an appropriate call must be made to SecureMessageParser's
parseSignedCleartextMessage() or parseSigncryptedMessage() method, depending on
which of the two message types was sent.
To provide better support for building cryptographic protocols, we also provide
a utility class called PublicKeyProtoUtil that assists with encoding and
parsing public keys in a simple wire format, as well as generating new key
pairs. In particular, this class can be used to dramatically simplify
Diffie-Hellman key exchanges.
# Caveats
There is a some excess overhead incurred for using this library, as compared to
a more "direct" implementation of almost any of the offered functionality. The
excess overhead is the price being paid for simplicity and robustness, both in
the API and in the implementation. If saving every CPU cycle or every bit of
bandwidth is of crucial importance to you, do not use this library (for
example, it would not make for a good SSL replacement for high volume traffic).
To get a sense for magnitude of the SecureMessage overhead, a symmetric key
based HMAC SHA-256 and AES-256 CBC mode authenticated encryption incurs a
maximum of about 80 bytes of overhead with SecureMessage, as opposed to a
maximum of about 64 bytes of overhead using a direct implementation of the same
thing.
Encryption without signature is intentionally unsupported. Historically,
offering encryption-only APIs has lead to a plethora of mistakes in protocol
design and implementation, since it is frequently assumed that encrypted data
cannot be tampered with (but this is not the case in practice).
Support for public key encryption is not yet available, although it may be
added in the future. Instead, we recommend to design protocols that use
(EC)Diffie-Hellman key exchanges, and then used the exchanged symmetric key for
encryption. For instance, this approach can offer forward secrecy, and
increased efficiency when multiple messages are concerned. Note that it is
easy to authenticate the Diffie-Hellman keys using a signature-only
SecureMessage wrapping with a public key signature scheme.
# Checkout instructions
```
git clone https://github.com/google/securemessage
cd securemessage
git submodule update --init --recursive
```
# Compilation and Use
See language specific implementation directories