BouncyCastle Keystores (BKS and UBER)

This module implements readers for keystores created by the BouncyCastle cryptographic provider for Java.

Store types

Pyjks supports two BouncyCastle store types:
  • BKS
  • UBER

Neither BKS or JKS/JCEKS stores make any effort to hide how many entries are present in the store, what their aliases are, and what type of key each entry contains. The keys inside each entry are still protected, and the store is protected against tampering via the store password, but anyone can still see the names and types of keys inside.

UBER keystores are similar to BKS, but they have an additional design goal: protect the store from introspection. This is done by additionally encrypting the entire keystore using (a key derived from) the store password.

class jks.bks.BksKeyStore(store_type, entries, version=2)[source]

Bases: jks.util.AbstractKeystore

Bouncycastle “BKS” keystore parser. Supports both the current V2 and old V1 formats.

entries

A dictionary of all entries in the keystore, mapped by alias.

store_type

A string indicating the type of keystore that was loaded. Equals bks for instances of this class.

classmethod load(filename, store_password, try_decrypt_keys=True)

Convenience wrapper function; reads the contents of the given file and passes it through to loads(). See loads().

classmethod loads(data, store_password, try_decrypt_keys=True)[source]

See jks.jks.KeyStore.loads().

Parameters:
  • data (bytes) – Byte string representation of the keystore to be loaded.
  • password (str) – Keystore password string
  • try_decrypt_keys (bool) – Whether to automatically try to decrypt any encountered key entries using the same password as the keystore password.
Returns:

A loaded BksKeyStore instance, if the keystore could be successfully parsed and the supplied store password is correct.

If the try_decrypt_keys parameters was set to True, any keys that could be successfully decrypted using the store password have already been decrypted; otherwise, no atttempt to decrypt any key entries is made.

Raises:
save(filename, store_password)

Convenience wrapper function; calls the saves() and saves the content to a file.

certs

A subset of the entries dictionary, filtered down to only those entries of type BksTrustedCertEntry.

plain_keys

A subset of the entries dictionary, filtered down to only those entries of type BksKeyEntry.

sealed_keys

A subset of the entries dictionary, filtered down to only those entries of type BksSealedKeyEntry.

secret_keys

A subset of the entries dictionary, filtered down to only those entries of type BksSecretKeyEntry.

version = None

Version of the keystore format, if loaded.

class jks.bks.UberKeyStore(store_type, entries, version=1)[source]

Bases: jks.bks.BksKeyStore

BouncyCastle “UBER” keystore format parser.

entries

A dictionary of all entries in the keystore, mapped by alias.

store_type

A string indicating the type of keystore that was loaded. Equals uber for instances of this class.

classmethod load(filename, store_password, try_decrypt_keys=True)

Convenience wrapper function; reads the contents of the given file and passes it through to loads(). See loads().

classmethod loads(data, store_password, try_decrypt_keys=True)[source]

See jks.jks.KeyStore.loads().

Parameters:
  • data (bytes) – Byte string representation of the keystore to be loaded.
  • password (str) – Keystore password string
  • try_decrypt_keys (bool) – Whether to automatically try to decrypt any encountered key entries using the same password as the keystore password.
Returns:

A loaded UberKeyStore instance, if the keystore could be successfully parsed and the supplied store password is correct.

If the try_decrypt_keys parameters was set to True, any keys that could be successfully decrypted using the store password have already been decrypted; otherwise, no atttempt to decrypt any key entries is made.

Raises:
save(filename, store_password)

Convenience wrapper function; calls the saves() and saves the content to a file.

certs

A subset of the entries dictionary, filtered down to only those entries of type BksTrustedCertEntry.

plain_keys

A subset of the entries dictionary, filtered down to only those entries of type BksKeyEntry.

sealed_keys

A subset of the entries dictionary, filtered down to only those entries of type BksSealedKeyEntry.

secret_keys

A subset of the entries dictionary, filtered down to only those entries of type BksSecretKeyEntry.

version = None

Version of the keystore format, if loaded.

Entry types

jks.bks.KEY_TYPE_PRIVATE = 0

Type indicator for private keys in BksKeyEntry.

jks.bks.KEY_TYPE_PUBLIC = 1

Type indicator for public keys in BksKeyEntry.

jks.bks.KEY_TYPE_SECRET = 2

Type indicator for secret keys in BksKeyEntry. Indicates a key for use with a symmetric encryption algorithm.

class jks.bks.BksTrustedCertEntry(**kwargs)[source]

Bases: jks.jks.TrustedCertEntry

Represents a trusted certificate entry in a BKS or UBER keystore.

type

A string indicating the type of certificate. Unless in exotic applications, this is usually X.509.

cert

A byte string containing the actual certificate data. In the case of X.509 certificates, this is the DER-encoded X.509 representation of the certificate.

decrypt(key_password)

Does nothing for this entry type; certificates are inherently public data and are not stored in encrypted form.

encrypt(key_password)

Does nothing for this entry type; certificates are inherently public data and are not stored in encrypted form.

is_decrypted()

Always returns True for this entry type.

classmethod new(alias, cert)

Helper function to create a new TrustedCertEntry.

Parameters:
  • alias (str) – The alias for the Trusted Cert Entry
  • certs (str) – The certificate, as a byte string.
Returns:

A loaded TrustedCertEntry instance, ready to be placed in a keystore.

class jks.bks.BksKeyEntry(type, format, algorithm, encoded, **kwargs)[source]

Bases: jks.bks.AbstractBksEntry

Represents a non-encrypted cryptographic key (public, private or secret) stored in a BKS keystore. May exceptionally appear as a top-level entry type in (very) old keystores, but you are most likely to encounter these as the nested object inside a BksSealedKeyEntry once decrypted.

When type is KEY_TYPE_PRIVATE, the following attributes are available:

pkey

Note

Only accessible after a call to decrypt(); until then, accessing this attribute will raise a NotYetDecryptedException. See also try_decrypt_keys on loads().

A byte string containing the value of the privateKey field of the PKCS#8 PrivateKeyInfo representation of the private key. See RFC 5208, section 5: Private-Key Information Syntax.

pkey_pkcs8

Note

Only accessible after a call to decrypt(); until then, accessing this attribute will raise a NotYetDecryptedException. See also try_decrypt_keys on loads().

A byte string containing the DER-encoded PKCS#8 PrivateKeyInfo representation of the private key. See RFC 5208, section 5: Private-Key Information Syntax.

algorithm_oid

Note

Only accessible after a call to decrypt(); until then, accessing this attribute will raise a NotYetDecryptedException. See also try_decrypt_keys on loads().

A tuple of integers corresponding to the algorithm OID for which the private key is valid.

Common values include:

  • (1,2,840,113549,1,1,1) (alias rsaEncryption)
  • (1,2,840,10040,4,1) (alias id-dsa).

When type is KEY_TYPE_PUBLIC, the following attributes are available:

public_key

Note

Only accessible after a call to decrypt(); until then, accessing this attribute will raise a NotYetDecryptedException. See also try_decrypt_keys on loads().

A byte string containing the value of the subjectPublicKey field of the X.509 SubjectPublicKeyInfo representation of the public key. See RFC 5280, Appendix A. Pseudo-ASN.1 Structures and OIDs.

public_key_info

Note

Only accessible after a call to decrypt(); until then, accessing this attribute will raise a NotYetDecryptedException. See also try_decrypt_keys on loads().

A byte string containing the DER-encoded X.509 SubjectPublicKeyInfo representation of the public key. See RFC 5280, Appendix A. Pseudo-ASN.1 Structures and OIDs.

algorithm_oid

Note

Only accessible after a call to decrypt(); until then, accessing this attribute will raise a NotYetDecryptedException. See also try_decrypt_keys on loads().

A tuple of integers corresponding to the algorithm OID for which the public key is valid.

Common values include:

  • (1,2,840,113549,1,1,1) (alias rsaEncryption)
  • (1,2,840,10040,4,1) (alias id-dsa).

When type is KEY_TYPE_SECRET, the following attributes are available:

key

Note

Only accessible after a call to decrypt(); until then, accessing this attribute will raise a NotYetDecryptedException. See also try_decrypt_keys on loads().

A byte string containing the raw secret key.

key_size

Note

Only accessible after a call to decrypt(); until then, accessing this attribute will raise a NotYetDecryptedException. See also try_decrypt_keys on loads().

An integer containing the size of the key, in bits. For DES and 3DES keys, the sizes 64 bits resp. 192 bits are returned.

type = None

An integer indicating the type of key: one of KEY_TYPE_PRIVATE, KEY_TYPE_PUBLIC, KEY_TYPE_SECRET.

format = None

A string indicating the format or encoding in which the key is stored. One of: PKCS8, PKCS#8, X.509, X509, RAW.

algorithm = None

A string indicating the algorithm for which the key is valid.

encoded = None

A byte string containing the key, formatted as indicated by the format attribute.

is_decrypted()[source]

Always returns True for this entry type.

decrypt(key_password)[source]

Does nothing for this entry type; these entries are stored in non-encrypted form.

classmethod type2str(t)[source]

Returns a string representation of the given key type. Returns one of PRIVATE, PUBLIC or SECRET, or None if no such key type is known.

Parameters:t (int) – Key type constant. One of KEY_TYPE_PRIVATE, KEY_TYPE_PUBLIC, KEY_TYPE_SECRET.
encrypt(key_password)

Encrypts the entry using the given password, so that it can be saved.

Parameters:key_password (str) – The password to encrypt the entry with.
classmethod new(alias)

Helper function to create a new KeyStoreEntry.

class jks.bks.BksSecretKeyEntry(**kwargs)[source]

Bases: jks.bks.AbstractBksEntry

Conceptually similar to, but not to be confused with, BksKeyEntry objects of type KEY_TYPE_SECRET:

  • BksSecretKeyEntry objects store the result of arbitrary user-supplied byte[]s, which, per the Java Keystore SPI, keystores are obligated to assume have already been protected by the user in some unspecified way. Because of this assumption, no password is provided for these entries when adding them to the keystore, and keystores are thus forced to store these bytes as-is.

    Produced by a call to KeyStore.setKeyEntry(String alias, byte[] key, Certificate[] chain) call.

    The bouncycastle project appears to have completely abandoned these entry types well over a decade ago now, and it is no longer possible to retrieve these entries through the Java APIs in any (remotely) recent BC version.

  • BksKeyEntry objects of type KEY_TYPE_SECRET store the result of a getEncoded() call on proper Java objects of type SecretKey.

    Produced by a call to KeyStore.setKeyEntry(String alias, Key key, char[] password, Certificate[] chain).

    The difference here is that the KeyStore implementation knows it’s getting a proper (Secret)Key Java object, and can decide for itself how to store it given the password supplied by the user. I.e., in this version of setKeyEntry it is left up to the keystore implementation to encode and protect the supplied Key object, instead of in advance by the user.

key = None

A byte string containing the secret key/value.

is_decrypted()[source]

Always returns True for this entry type.

decrypt(key_password)[source]

Does nothing for this entry type; these entries stored arbitrary user-supplied data, unclear how to decrypt (may not be encrypted at all).

encrypt(key_password)

Encrypts the entry using the given password, so that it can be saved.

Parameters:key_password (str) – The password to encrypt the entry with.
classmethod new(alias)

Helper function to create a new KeyStoreEntry.

class jks.bks.BksSealedKeyEntry(**kwargs)[source]

Bases: jks.bks.AbstractBksEntry

PBEWithSHAAnd3-KeyTripleDES-CBC-encrypted wrapper around a BksKeyEntry. The contained key type is unknown until decrypted.

Once decrypted, objects of this type can be used in the same way as BksKeyEntry: attribute accesses are forwarded to the wrapped BksKeyEntry object.

is_decrypted()[source]

Returns True if the entry has already been decrypted, False otherwise.

decrypt(key_password)[source]

Decrypts the entry using the given password. Has no effect if the entry has already been decrypted.

Parameters:

key_password (str) – The password to decrypt the entry with.

Raises:
encrypt(key_password)

Encrypts the entry using the given password, so that it can be saved.

Parameters:key_password (str) – The password to encrypt the entry with.
classmethod new(alias)

Helper function to create a new KeyStoreEntry.