This is a proposal for a new "keystore" format, to be used by GNU Java implementations (Classpath, GCJ, GNU Crypto). 0. Data types. The keystore itself is just a binary file of raw octets. Data read and written to keystores will be one of the following types: uint8 An unsigned byte. uint16 An unsigned two-byte integer, in big-endian byte order. unit32 An unsigned four-byte integer. uint64 An unsigned eight-byte integer. string An arbitrary byte array, stored as 1) the length of the byte array, encoded in a uint16. 2) the bytes themselves. u8string A string, but the byte array is interpreted as a string of UTF-8 characters. bigint An arbitrary-precision integer stored in two's compliment notation, stored as a string. octets[l] A fixed-length byte array, stored without length. The length, l, must be implied by the format. 1. Magic bytes/version number. To identify keystores by content, and to protect against incompatibilities when the format evolves, all keystores will begin with the following bytes: octets[3] The bytes "GKS". uint8 Version number. The current version number shall be 1. Thus keystores described in this document shall begin with the value 0x474b5301. In magic(5) parlance, this would be: 0 string GKS GNU key store file >3 byte x version %d 2. Content-types. The keystore shall then contain one or more constructs of the following form: byte Content-type. octets[n] Data, dependent upon content-type. GNU version 1 keystores shall have the following types defined: 2.1. Extension value. #define GKS_TYPE_EXTENSION 255 This value shall be reserved for extensions, and it must not appear in GKS version 1 files. 2.2. End of keystore. #define GKS_TYPE_END 0 This sentinel marks the end of meaningful values in the keystore, or in a list of enveloped entries. No further data should be considered after this is read. byte GKS_TYPE_END 2.3. Trusted Certificates. #define GKS_TYPE_CERT 1 This value denotes a "trusted certificate entry". byte GKS_TYPE_CERT u8string Entry alias. uint64 Entry creation date. u8string Encoding name. string Encoded certificate. 2.4. Private Keys. #define GKS_TYPE_PRIVATE_KEY 2 This value denotes a private key. byte GKS_TYPE_PRIVATE_KEY u8string Entry alias. uint64 Entry creation date. u8string Key type. string Encoded key. 2.5. Certificate Chain. #define GKS_TYPE_CERT_CHAIN 3 This value denotes a certificate chain, which compliments a private key with the same alias name. Each private key should have a corresponding certificate chain, but this is not required by the format. byte GKS_TYPE_CERT_CHAIN u8string Entry alias. uint64 Entry creation date. u8string Chain type. string Encoded certificate chain. 3. Envelope types. Envelope types contain other types, usually to transform the type they contain. There are two types of enveloped data: single and multiple. Single enveloped types encode one subtype; multiple enveloped types contain zero or more types, ending with GKS_TYPE_END. 3.1. Password-encrypted. #define GKS_TYPE_PBE 4 Password-encrypted enveloped types use a combination of a password key-derivation function and a block cipher. The padding scheme used shall be that described in PKCS #7. We use OIDs here for portability, and to encode cipher, key length, and mode in a concise form. The KDF is always KDF2 as described in PKCS #5. The PRF (hash-based mac) is given by the OID of the underlying hash function. The default algorithms are: 1.3.6.1.4.1.11591.12.2 - Tiger/192. 1.3.6.1.4.1.11591.13.2.2 - Serpent-128 in CBC mode. byte GKS_TYPE_PBE u8string PBE KDF2 PRF algorithm OID. uint32 Iteration count. string Salt. u8string Encryption algorithm OID. string Encrypted data. 3.2. Password-Encrypted Entries. #define GKS_TYPE_PBE_ENTRY 5 Password-encrypted entries are equivalent to GKS_TYPE_PBE, except they contain a single enveloped type, and inherit the "alias name" of their enclosed type. Therefore, entries of this type may only contain types that have an alias associated with them. byte GKS_TYPE_PBE_ENTRY u8string Alias name. u8string PBE KDF2 PRF algorithm OID. uint32 Iteration count. string Salt. u8string Encryption algorithm OID. string Encrypted entry. 3.3. Password-Authenticated. #define GKS_TYPE_PBMAC 6 Password-authenticated enveloped types use a password KDF in similar fashion as encrypted enveloped types, except there is no need to pad the to-be-authenticated input. byte GKS_TYPE_PBMAC u8string PBE KDF2 PRF algorithm OID. uint32 Iteration count. string Salt. u8string Hash-based mac OID. string Authenticated data. octets[l] Mac of the data. l is dependent upon the output length of the mac algorithm. 3.4. Password-Authenticated Entries. #define GKS_TYPE_PBMAC_ENTRY 7 Password-authenticated entries are the single-entry analog to GKS_TYPE_PBE_ENTRY. byte GKS_TYPE_PBMAC_ENTRY u8string Alias name. u8string PBE KDF2 PRF algorithm OID. uint32 Iteration count. string Salt. u8string Hash-based mac OID. string Authenticated data. octets[l] Mac of the data. l is dependent upon the output length of the mac algorithm. 4. Recommended constructions. The recommended construction for the keystore is as follows: GKS_TYPE_PBMAC { ... zero or more types. GKS_TYPE_END } GKS_TYPE_CERT and GKS_TYPE_CERT_CHAIN should be stored in the above construction as-is. For GKS_TYPE_PRIVATE_KEY, we recommend the following construction: GKS_TYPE_PBE_ENTRY { GKS_TYPE_PBMAC_ENTRY { GKS_TYPE_PRIVATE_KEY } } 5. Motivation. The need for a new file format is not immediately obvious; there are, for example, the JKS format Sun uses and the PKCS #12 format. JKS is a proprietary, limited format that nearly constitutes a "toy" algorithm. PKCS #12 is a more generic format and does not lend itself well to the password-protected paradigm of Java keystores. With this format we introduce a method of long-term storage for trusted certificates and private credentials that is both secure and extensible. The format easily fits the KeyStore API of the Java platform while not being limited to it.