def _convert_blob_to_bin(self, secret_blob): try: ciphertext_bin = b64decode(secret_blob) except Exception: raise errors.InputError("ciphertext blob is not base64 encoded") if self.offset > len(ciphertext_bin): raise errors.InputError("RSA ciphertext length is larger than the " "secret ciphertext binary length") return ciphertext_bin
def _set_decryptor(self, plaintext_private_key=None, encrypted_private_key=None): '''Creates a OAEP decryptor based on a RSA private key.''' if self.decryptor is not None: return if not plaintext_private_key: if not encrypted_private_key: try: with open(self.encrypted_private_key_file, 'rb') as f: encrypted_private_key = f.read() except IOError as e: raise errors.InputError( "private key '%s' does not exist." % (self.encrypted_private_key_file)) plaintext_private_key = self._get_plaintext_private_key( encrypted_private_key, encryption_context=self.encryption_context) try: private_key_obj = serialization.load_pem_private_key( plaintext_private_key, password=None, backend=default_backend()) self.decryptor = Decryptor(private_key_obj) except Exception as e: raise errors.DecryptorError( "private key is malformed. (Reason: %s)" % (str(e)))
def _encrypt_all_secrets(self, secrets_json): '''Helper function to encrypt all secrets from a JSON string''' try: secrets = json.loads(secrets_json) except ValueError: raise errors.InputError('input is not valid JSON') for secret_name, secret in secrets.items(): log.info(secret_name) self._encrypt(secret_name, secret)
def _validate_secret(self, secret_name, secret, blob_mode): if not blob_mode: # secret must have a value if len(secret_name) == 0: raise errors.InputError( "secret name '%s' must be greather than length of 0" % (secret_name)) # secret name can only contain ascii characters if not self._is_ascii(secret_name): raise errors.InputError( "secret name '%s' must contain only ASCII chararacters" % (secret_name)) # warn when secret value contains non-ascii chars if not self._is_ascii(secret): log.warn("Secret '%s' contains non-ASCII characters!" % (secret_name)) # warn when secret value contains escape characters (e.g. "\r") if "\\" in secret: log.warn("Secret '%s' contains escape sequence characters!" % (secret_name))
def _set_encryptor(self, public_key): '''Creates a OAEP decryptor based on a RSA private key.''' if self.encryptor is not None: return if not public_key: try: with open(self.public_key_file, 'rb') as f: public_key = f.read() except IOError as e: raise errors.InputError("public key '%s' does not exist." % self.public_key_file) try: public_key_obj = serialization.load_pem_public_key( public_key, backend=default_backend()) self.encryptor = Encryptor(public_key_obj) except Exception as e: raise errors.EncryptorError( "public key is malformed. (Reason: %s)" % (str(e)))
def _decrypt_secret_blob(self, secret_blob): '''Decrypts a binary blob which contains an RSA encrypted AES session key and AES encrypted data.''' # Break out base64 encoded binary to encrypted session key and data ciphertext_bin = self._convert_blob_to_bin(secret_blob) encrypted_session_key = ciphertext_bin[:self.offset] ciphertext = ciphertext_bin[self.offset:] secret = None try: # decrypt aes session key with rsa private key session_key = self.decryptor.decrypt(encrypted_session_key) fernet_cipher = Fernet(session_key) secret = fernet_cipher.decrypt(ciphertext).decode('utf-8') # A number of ciphertext issues could cause AES-RSA decryption to fail except Exception: raise errors.InputError("ciphertext binary is corrupt") return secret
def main(): config = get_config(sys.argv) if config.debug: logging.basicConfig(level=logging.DEBUG) elif config.verbose: logging.basicConfig(level=logging.INFO) elif config.quiet: logging.disable(sys.maxint) else: logging.basicConfig() if config.version: print("Code Crypt - " + str(__version__)) return if config.env not in defaults.ENV_TAGS: print("Error: env must be set to one of the following: %s" % ( str(defaults.ENV_TAGS))) exit(1) env = config.env code_crypt_obj = code_crypt.CodeCrypt( kms_key_id=config.kms_key_id, env=env) try: if config.init: code_crypt_obj.generate_key_pair() return if config.decrypt: secret = code_crypt_obj.decrypt(config.decrypt) if secret: print(secret) return if config.decrypt_all: secrets = code_crypt_obj.decrypt() print(json.dumps(secrets, indent=2)) return if config.import_secrets: secrets_file = config.import_secrets try: with open(secrets_file, 'r') as f: secrets_json = f.read() except IOError as e: raise errors.InputError("secrets file '%s' does not exist" % ( secrets_file)) code_crypt_obj.import_secrets(secrets_json) return if config.encrypt: if '=' not in config.encrypt: raise errors.InputError("provide a key value pair (usage: " "--encrypt SOME_SECRET_NAME=some_" "secret_value)") keyval = config.encrypt.split('=', 1) code_crypt_obj.encrypt(keyval[0], keyval[1]) return if config.blob_encrypt: blob = code_crypt_obj.blob_encrypt(config.blob_encrypt) print(blob) return if config.blob_decrypt: secret = code_crypt_obj.blob_decrypt(config.blob_decrypt) if secret: print(secret) return except errors.CodeCryptError as e: print(str(e.message)) exit(1)