| # 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 |