Mysql – the best way to store SSH fingerprints and public keys

database-designencryptionfieldsmysql-5.7Security

I'm building a virtual Keyring in our DB to allow users to store PGP/GPG public keys with relation to email addresses so that they can optionally encrypt all communications our system sends them. I'm just building the table now and wasn't sure about the column type to store the fingerprint.

From what I understand fingerprints will be 128 or 160 bits long, generally in the form of:

43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8

… which I believe is just a 32bit MD5 hash / UUID. I'm guessing I can store this as a 16bit Binary value, or a 32 char string…

Is there a best practice, and if so what is it, or lacking that, what's your preference?

As a related follow up, is there any reason to Encrypt the public key string itself, or is that redundant since it is public after all?


EDIT: BTW, this is MySQL currently 5.5, but will be 5.7 in the near future.**


EDIT 2: I can't find any examples out there of a table schema for storing this type of record and I admittedly have only minimal understanding beyond the basics of using public/private keys in my own role, so while I could discern that the fingerprint is a hash, I'm unaware of the different formats for public keys and what range their lengths can come in (i.e. what about the -----BEGIN CERTIFICATE----- components, what size field will these need?).

If possible can someone provide a basic CREATE TABLE statement with what you see as an optimal fieldset? Below is what I've created thus far, is it sufficient, would you change anything?

CREATE TABLE `public_keys` (
    `ai_col`  int UNSIGNED NOT NULL AUTO_INCREMENT ,
    /* ... other foreign keys ... */
    `label`  varchar(100) NULL ,
    `fingerprint`  binary(16) NOT NULL ,
    `key_type`  varchar(10) NOT NULL ,
    `public_key`  varchar(1024) NULL ,
    PRIMARY KEY (`ai_col`)
);

Best Answer

If I'm not mistaken, the fingerprint is a hexadecimal number. That means you could store it as a binary number, since two hexadecimal characters can be represented by a single byte, making a 32-character hexadecimal string = 16 bytes.

Here's the documentation on binary and varbinary data types for MySQL 5.7 (I don't have a test environment handy).

I do something similar for IP addresses based on this question and answer from StackExchange. Store the data as binary, convert it back to text when it needs to be displayed or compared against another string. Create a view that calls the functions as a part of it so you can easily get and store the full string when you want it.

Also, public keys are indeed public, and are often stored in searchable databases like this one.