leekspin.crypto

General cryptographic utilities.

exception InvalidFingerprint[source]

Bases: exceptions.ValueError

Raised when a key fingerprint is invalid.

addPKCS1Padding(message)[source]

Add PKCS#1 padding to message.

Todo

What version of PKCS#1? PKCS#1 v1.0? See https://bugs.torproject.org/13042.

Each block is 128 bytes total in size:

  • 2 bytes for the type info (‘x00x01’)
  • 1 byte for the separator (‘x00’)
  • variable length padding (‘xFF’)
  • variable length for the message
Parameters:message (str) – The message will be encoded as bytes before adding PKCS#1 padding.
Return type:bytes
Returns:The PKCS#1 padded message.
addTorPKHeaderAndFooter(publicKey)[source]

Add the ----BEGIN RSA PUBLIC KEY----- and -----END RSA PUBLIC KEY----- headers to a publicKey.

Parameters:publicKey (bytes) – A headerless, chunked, base64-encoded, PKCS#1-padded, ASN.1 DER sequence string representation of a public RSA key.
Return type:bytes
Returns:The same signature, with the headers which Tor uses around it.
addTorSigHeaderAndFooter(signature)[source]

Add the ----BEGIN SIGNATURE----- and -----END SIGNATURE----- headers to a signature.

Parameters:signature (bytes) – A headerless, chunked, base64-encoded signature.
Return type:bytes
Returns:The same signature, with the headers which Tor uses around it.
bytesToLong(bites)[source]

Convert a byte string to a long integer.

This function was stolen from BridgeDB, commit 5ed5c42e.

>>> from bridgedb.crypto import bytesToLong
>>> bytesToLong('\x059')
1337L
>>> bytesToLong('I\x96\x02\xd2')
1234567890L
>>> bytesToLong('\x00\x00\x00\x00I\x96\x02\xd2')
1234567890L
>>> bytesToLong('\xabT\xa9\x8c\xeb\x1f\n\xd2')
12345678901234567890L
Parameters:bites (bytes) – The byte string to convert.
Return type:long
longToBytes(number, blocksize=0)[source]

Convert a long integer to a byte string.

This function was stolen from BridgeDB, commit 5ed5c42e.

>>> from bridgedb.crypto import longToBytes
>>> longToBytes(1337L)
'\x059'
>>> longToBytes(1234567890L)
'I\x96\x02\xd2'
>>> longToBytes(1234567890L, blocksize=8)
'\x00\x00\x00\x00I\x96\x02\xd2'
>>> longToBytes(12345678901234567890L)
'\xabT\xa9\x8c\xeb\x1f\n\xd2'
Parameters:
  • number (int) – The long integer to convert.
  • blocksize (int) – If blocksize is given and greater than zero, pad the front of the byte string with binary zeros so that the length is a multiple of blocksize.
Return type:

bytes

chunkInto64CharsPerLine(data, separator='\n')[source]

Chunk data into lines with 64 characters each.

Parameters:
  • data (basestring) – The data to be chunked up.
  • separator (basestring) – The character to use to join the chunked lines.
Return type:

basestring

Returns:

The data, as a string, with 64 characters (plus the separator character), per line.

convertToSmooshedFingerprint(fingerprint)[source]

Convert to a space-delimited 40 character fingerprint

Given a 49-character string, such as one returned from convertToSpaceyFingerprint():

72C2 F0AE 1C14 F40E D37E D5F5 434B 6471 1A65 8E46

convert it to the following format:

72C2F0AE1C14F40ED37ED5F5434B64711A658E46
Parameters:fingerprint (str) – A 49-character spacey fingerprint.
Return type:bytes
Raises InvalidFingerprint:
 If the fingerprint isn’t 49-bytes in length.
Returns:A 40-character smooshed fingerprint without spaces.
convertToSpaceyFingerprint(fingerprint)[source]

Convert to a space-delimited 40-character fingerprint

Given a 40 character string, usually the the SHA-1 hash of the DER encoding of an ASN.1 RSA public key, such as:

72C2F0AE1C14F40ED37ED5F5434B64711A658E46

convert it to the following format:

72C2 F0AE 1C14 F40E D37E D5F5 434B 6471 1A65 8E46
Parameters:fingerprint (str) – A 40-character hex fingerprint.
Return type:bytes
Raises InvalidFingerprint:
 If the fingerprint isn’t 40 bytes in length.
Returns:A 4-character space-delimited fingerprint.
digestDescriptorContent(content)[source]
getASN1Sequence(privateKey)[source]

Get an ASN.1 DER sequence string representation of the key’s public modulus and exponent.

Parameters:privateKey (Crypto.PublicKey.RSA) – A private RSA key.
Return type:bytes
Returns:The ASN.1 DER-encoded string representation of the public portions of the privateKey.
getFingerprint(publicKey)[source]

Get a digest of the ASN.1 DER-encoded publicKey.

Parameters:publicKey (str) – A public key (as within the return parameters of generateOnionKey() or generateSigningKey().)
Return type:str
Returns:A spacey fingerprint.
_generateRSAKey(bits=1024)[source]

Generate an RSA key, suitable for e.g. a router/bridge signing or onion key, or an Hidden Service service or permanent key.

The encodings for the various key and descriptor digests needed are described in dir-spec.txt and tor-spec.txt, the latter mostly for the padding and encoding used in the creation of an OR’s keys.

Parameters:bits (int) – The length of the RSA key, in bits.
Returns:A tuple of strings, (key-private, key-public, key-line), where key-line should be appropriate for placement directly into a descriptor.
generateOnionKey(bits=1024)[source]

Generate a router’s onion key, which is used to encrypt CERT cells.

The encodings for the various key and descriptor digests needed are described in dir-spec.txt and tor-spec.txt, the latter mostly for the padding and encoding used in the creation of an OR’s keys.

For the router line in a networkstatus document, the following encodings are specified:

[…] “Identity” is a hash of its identity key, encoded in base64, with trailing equals sign(s) removed. “Digest” is a hash of its most recent descriptor as signed (that is, not including the signature), encoded in base64.

dir-spec.txt L1504-1512

Before the hash digest of an OR’s identity key is base64-encoded for inclusion in a networkstatus document, the hash digest is created in the following manner:

When we refer to “the hash of a public key”, we mean the SHA-1 hash of the DER encoding of an ASN.1 RSA public key (as specified in PKCS.1). […] The “legacy identity” and “identity fingerprint” fields are the SHA1 hash of the PKCS#1 ASN1 encoding of the next onion router’s identity (signing) key.

tor-spec.txt L109-110 and L784-786

Parameters:bits (int) – The length of the RSA key, in bits.
Returns:A tuple of strings, (onion-key-private, onion-key-public, onion-key-line), where onion-key-line should directly go into a server-descriptor.
generateSigningKey(bits=1024)[source]

Generate a router’s signing-key, which is used to sign e.g. descriptor contents.

Parameters:bits (int) – The length of the RSA key, in bits.
Returns:A tuple of strings, (signing-key-private, signing-key-public, signing-key-line), where signign-key-line should directly go into a descriptor.
signDescriptorContent(content, privateKey, digest=None, token='router-signature\n')[source]

Sign the content or the digest of the content, and postpend it to the content.

Parameters:
  • content (str) – The contents of a descriptor.
  • privateKey (Crypto.PublicKey.RSA) – A private RSA key.
  • digest (str or None) – If given, this should be the PKCS#1-padded binary digest of the descriptor contents (i.e. the third return value from digestDescriptorContent()). If the digest is given, then this digest will be signed. Otherwise, if None, then contents will be signed.
  • token (str) – The token to search for when appending the signature to the end of the descriptor content