1Secure Systems Library 2---------------------- 3 4.. image:: https://travis-ci.org/secure-systems-lab/securesystemslib.svg?branch=master 5 :target: https://travis-ci.org/secure-systems-lab/securesystemslib 6 7.. image:: https://coveralls.io/repos/github/secure-systems-lab/securesystemslib/badge.svg?branch=master 8 :target: https://coveralls.io/github/secure-systems-lab/securesystemslib?branch=master 9 10.. image:: https://pyup.io/repos/github/secure-systems-lab/securesystemslib/shield.svg 11 :target: https://pyup.io/repos/github/secure-systems-lab/securesystemslib/ 12 :alt: Updates 13 14A library that provides cryptographic and general-purpose functions for Secure 15Systems Lab projects at NYU. The routines are general enough to be usable by 16other projects. 17 18Overview 19++++++++ 20 21securesystemslib supports public-key and general-purpose cryptography, such as 22`ECDSA 23<https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm>`_, 24`Ed25519 <http://ed25519.cr.yp.to/>`_, `RSA 25<https://en.wikipedia.org/wiki/RSA_%28cryptosystem%29>`_, SHA256, SHA512, etc. 26Most of the cryptographic operations are performed by the `cryptography 27<https://cryptography.io/en/latest/>`_ and `PyNaCl 28<https://github.com/pyca/pynacl>`_ libraries, but verification of Ed25519 29signatures can be done in pure Python. 30 31The `cryptography` library is used to generate keys and signatures with the 32ECDSA and RSA algorithms, and perform general-purpose cryptography such as 33encrypting keys. The PyNaCl library is used to generate Ed25519 keys and 34signatures. PyNaCl is a Python binding to the Networking and Cryptography 35Library. For key storage, RSA keys may be stored in PEM or JSON format, and 36Ed25519 keys in JSON format. Generating, importing, and loading cryptographic 37key files can be done with functions available in securesystemslib. 38 39Installation 40++++++++++++ 41 42:: 43 44 $ pip install securesystemslib 45 46 47The default installation only supports Ed25519 keys and signatures (in pure 48Python). Support for RSA, ECDSA, and E25519 via the `cryptography` and 49`PyNaCl` libraries is available by installing the `crypto` and `pynacl` extras: 50 51:: 52 53 $ pip install securesystemslib[crypto] 54 $ pip install securesystemslib[pynacl] 55 56 57Create RSA Keys 58~~~~~~~~~~~~~~~ 59 60Note: In the instructions below, lines that start with *>>>* denote commands 61that should be entered by the reader, *#* begins the start of a comment, and 62text without prepended symbols is the output of a command. 63 64:: 65 66 >>> from securesystemslib.interface import * 67 68 # The following function creates an RSA key pair, where the private key is 69 # saved to "rsa_key1" and the public key to "rsa_key1.pub" (both saved to 70 # the current working directory). A full directory path may be specified 71 # instead of saving keys to the current working directory. If specified 72 # directories do not exist, they will be created. 73 >>> generate_and_write_rsa_keypair("rsa_key1", bits=2048, password="password") 74 75 # If the key length is unspecified, it defaults to 3072 bits. A length of 76 # less than 2048 bits raises an exception. A password may be supplied as an 77 # argument, otherwise a user prompt is presented. If the password is an 78 # empty string, the private key is saved unencrypted. 79 >>> generate_and_write_rsa_keypair("rsa_key2") 80 Enter a password for the RSA key: 81 Confirm: 82 83 84The following four key files should now exist: 85 861. rsa_key1 872. rsa_key1.pub 883. rsa_key2 894. rsa_key2.pub 90 91Import RSA Keys 92~~~~~~~~~~~~~~~ 93 94:: 95 96 # Continuing from the previous section . . . 97 98 # Import an existing public key. 99 >>> public_rsa_key1 = import_rsa_publickey_from_file("rsa_key1.pub") 100 101 # Import an existing private key. If your private key is encrypted, 102 # which it should be, you either have to pass a 'password' or enter one 103 # on the prompt. 104 >>> private_rsa_key1 = import_rsa_privatekey_from_file("rsa_key1", password='some passphrase") 105 OR: 106 >>> private_rsa_key1 = import_rsa_privatekey_from_file("rsa_key1", prompt=True) 107 Enter a password for the encrypted RSA key: 108 109**import_rsa_privatekey_from_file()** raises a 110*securesystemslib.exceptions.CryptoError* exception if the key / password is 111invalid: 112 113:: 114 115 securesystemslib.exceptions.CryptoError: RSA (public, private) tuple cannot 116 be generated from the encrypted PEM string: Bad decrypt. Incorrect password? 117 118Note: The specific message provided by the exception might differ depending on 119which cryptography library is used. 120 121Create and Import Ed25519 Keys 122~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 123 124:: 125 126 # Continuing from the previous section . . . 127 128 # Generate and write an Ed25519 key pair. The private key is saved 129 # encrypted. A 'password' argument may be supplied, otherwise a prompt is 130 # presented. 131 >>> generate_and_write_ed25519_keypair('ed25519_key') 132 Enter a password for the Ed25519 key: 133 Confirm: 134 135 # Import the Ed25519 public key just created . . . 136 >>> public_ed25519_key = import_ed25519_publickey_from_file('ed25519_key.pub') 137 138 # and its corresponding private key. 139 >>> private_ed25519_key = import_ed25519_privatekey_from_file('ed25519_key') 140 Enter a password for the encrypted Ed25519 key: 141 142 143Create and Import ECDSA Keys 144~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 145 146:: 147 148 # continuing from the previous sections . . . 149 150 >>> generate_and_write_ecdsa_keypair('ecdsa_key') 151 Enter a password for the ECDSA key: 152 Confirm: 153 154 >>> public_ecdsa_key = import_ecdsa_publickey_from_file('ecdsa_key.pub') 155 >>> private_ecdsa_key = import_ecdsa_privatekey_from_file('ecdsa_key') 156 Enter a password for the encrypted ECDSA key: 157 158 159Generate ECDSA, Ed25519, and RSA Signatures 160~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 161 162Note: Users may also access the crypto functions directly to perform 163cryptographic operations. 164 165:: 166 167 >>> from securesystemslib.keys import * 168 169 >>> data = 'The quick brown fox jumps over the lazy dog' 170 >>> ed25519_key = generate_ed25519_key() 171 >>> signature = create_signature(ed25519_key, data) 172 >>> rsa_key = generate_rsa_key(2048) 173 >>> signature = create_signature(rsa_key, data) 174 >>> ecdsa_key = generate_ecdsa_key() 175 >>> signature = create_signature(ecdsa_key, data) 176 177 178Verify ECDSA, Ed25519, and RSA Signatures 179~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 180 181:: 182 183 # Continuing from the previous sections . . . 184 185 >>> data = 'The quick brown fox jumps over the lazy dog' 186 >>> ed25519_key = generate_ed25519_key() 187 >>> signature = create_signature(ed25519_key, data) 188 >>> verify_signature(ed25519_key, signature, data) 189 True 190 >>> verify_signature(ed25519_key, signature, 'bad_data') 191 False 192 >>> rsa_key = generate_rsa_key() 193 >>> signature = create_signature(rsa_key, data) 194 >>> verify_signature(rsa_key, signature, data) 195 True 196 >>> ecdsa_key = generate_ecdsa_key() 197 >>> signature = create_signature(ecdsa_key, data) 198 >>> verify_signature(ecdsa_key, signature, data) 199 True 200 201 202Miscellaneous functions 203~~~~~~~~~~~~~~~~~~~~~~~ 204 205**create_rsa_encrypted_pem()** 206 207:: 208 209 # Continuing from the previous sections . . . 210 211 >>> rsa_key = generate_rsa_key() 212 >>> private = rsa_key['keyval']['private'] 213 >>> passphrase = 'secret' 214 >>> encrypted_pem = create_rsa_encrypted_pem(private, passphrase) 215 216**import_rsakey_from_public_pem()** 217 218:: 219 220 >>> rsa_key = generate_rsa_key() 221 >>> public = rsa_key['keyval']['public'] 222 >>> rsa_key2 = import_rsakey_from_public_pem(public) 223 224 225**import_rsakey_from_pem()** 226 227:: 228 229 >>> rsa_key = generate_rsa_key() 230 >>> public = rsa_key['keyval']['public'] 231 >>> private = rsa_key['keyval']['private'] 232 >>> rsa_key2 = import_rsakey_from_pem(public) 233 >>> rsa_key3 = import_rsakey_from_pem(private) 234 235 236**extract_pem()** 237 238:: 239 240 >>> rsa_key = generate_rsa_key() 241 >>> private_pem = extract_pem(rsakey['keyval']['private'], private_pem=True) 242 >>> public_pem = extract_pem(rsakey['keyval']['public'], private_pem=False) 243 244 245**encrypt_key()** 246 247:: 248 249 >>> ed25519_key = generate_ed25519_key() 250 >>> password = 'secret' 251 >>> encrypted_key = encrypt_key(ed25519_key, password) 252 253 254**decrypt_key()** 255 256:: 257 258 >>> ed25519_key = generate_ed25519_key() 259 >>> password = 'secret' 260 >>> encrypted_key = encrypt_key(ed25519_key, password) 261 >>> decrypted_key = decrypt_key(encrypted_key.encode('utf-8'), password) 262 >>> decrypted_key == ed25519_key 263 True 264 265 266**create_rsa_encrypted_pem()** 267 268:: 269 270 >>> rsa_key = generate_rsa_key() 271 >>> private = rsa_key['keyval']['private'] 272 >>> passphrase = 'secret' 273 >>> encrypted_pem = create_rsa_encrypted_pem(private, passphrase) 274 275 276**is_pem_public()** 277 278:: 279 280 >>> rsa_key = generate_rsa_key() 281 >>> public = rsa_key['keyval']['public'] 282 >>> private = rsa_key['keyval']['private'] 283 >>> is_pem_public(public) 284 True 285 >>> is_pem_public(private) 286 False 287 288 289**is_pem_private()** 290 291:: 292 293 >>> rsa_key = generate_rsa_key() 294 >>> private = rsa_key['keyval']['private'] 295 >>> public = rsa_key['keyval']['public'] 296 >>> is_pem_private(private) 297 True 298 >>> is_pem_private(public) 299 False 300 301 302**import_ecdsakey_from_private_pem()** 303 304:: 305 306 >>> ecdsa_key = generate_ecdsa_key() 307 >>> private_pem = ecdsa_key['keyval']['private'] 308 >>> ecdsa_key2 = import_ecdsakey_from_private_pem(private_pem) 309 310 311**import_ecdsakey_from_public_pem()** 312 313:: 314 315 >>> ecdsa_key = generate_ecdsa_key() 316 >>> public = ecdsa_key['keyval']['public'] 317 >>> ecdsa_key2 = import_ecdsakey_from_public_pem(public) 318 319 320**import_ecdsakey_from_pem()** 321 322:: 323 324 >>> ecdsa_key = generate_ecdsa_key() 325 >>> private_pem = ecdsa_key['keyval']['private'] 326 >>> ecdsa_key2 = import_ecdsakey_from_pem(private_pem) 327 >>> public_pem = ecdsa_key['keyval']['public'] 328 >>> ecdsa_key2 = import_ecdsakey_from_pem(public_pem) 329 330