1# -*- coding: utf-8 -*- 2# 3# Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu> 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17'''Large file support 18 19 - break a file into smaller blocks, and encrypt them, and store the 20 encrypted blocks in another file. 21 22 - take such an encrypted files, decrypt its blocks, and reconstruct the 23 original file. 24 25The encrypted file format is as follows, where || denotes byte concatenation: 26 27 FILE := VERSION || BLOCK || BLOCK ... 28 29 BLOCK := LENGTH || DATA 30 31 LENGTH := varint-encoded length of the subsequent data. Varint comes from 32 Google Protobuf, and encodes an integer into a variable number of bytes. 33 Each byte uses the 7 lowest bits to encode the value. The highest bit set 34 to 1 indicates the next byte is also part of the varint. The last byte will 35 have this bit set to 0. 36 37This file format is called the VARBLOCK format, in line with the varint format 38used to denote the block sizes. 39 40''' 41 42from rsa import key, common, pkcs1, varblock 43from rsa._compat import byte 44 45def encrypt_bigfile(infile, outfile, pub_key): 46 '''Encrypts a file, writing it to 'outfile' in VARBLOCK format. 47 48 :param infile: file-like object to read the cleartext from 49 :param outfile: file-like object to write the crypto in VARBLOCK format to 50 :param pub_key: :py:class:`rsa.PublicKey` to encrypt with 51 52 ''' 53 54 if not isinstance(pub_key, key.PublicKey): 55 raise TypeError('Public key required, but got %r' % pub_key) 56 57 key_bytes = common.bit_size(pub_key.n) // 8 58 blocksize = key_bytes - 11 # keep space for PKCS#1 padding 59 60 # Write the version number to the VARBLOCK file 61 outfile.write(byte(varblock.VARBLOCK_VERSION)) 62 63 # Encrypt and write each block 64 for block in varblock.yield_fixedblocks(infile, blocksize): 65 crypto = pkcs1.encrypt(block, pub_key) 66 67 varblock.write_varint(outfile, len(crypto)) 68 outfile.write(crypto) 69 70def decrypt_bigfile(infile, outfile, priv_key): 71 '''Decrypts an encrypted VARBLOCK file, writing it to 'outfile' 72 73 :param infile: file-like object to read the crypto in VARBLOCK format from 74 :param outfile: file-like object to write the cleartext to 75 :param priv_key: :py:class:`rsa.PrivateKey` to decrypt with 76 77 ''' 78 79 if not isinstance(priv_key, key.PrivateKey): 80 raise TypeError('Private key required, but got %r' % priv_key) 81 82 for block in varblock.yield_varblocks(infile): 83 cleartext = pkcs1.decrypt(block, priv_key) 84 outfile.write(cleartext) 85 86__all__ = ['encrypt_bigfile', 'decrypt_bigfile'] 87 88