2016年5月9日月曜日

Python でファイルの暗号化メモ

python でファイルの暗号化メモ

色んなExampleから抜き出して作成してみました。

angoka.py 暗号化ファイル

cAngo.py 暗号化実装ファイル

実行方法

$ python angoka.py




以下ソースファイル

#===== BEGIN angoka.py =======================================================
# encoding: utf-8

#####  pythonのpathは必要ならば書き加えてください。  #####
#####  print文の print('ooo') カッコでエラーとなる場合は print 'ooo' に書き換えてください  #####

import os, sys        # 既存ターゲットファイル削除
import getpass        # パスワード入力用
import termios        # Yes or No 入力用
import tty            # Yes or No 入力用
import subprocess     # shell command用
from cAngo import *   # 暗号・復号化用 cAngo.py

               
#===== Yes or No =================================
def yesno(message):
    result = ''
    sys.stdout.write(message)
    sys.stdout.flush()
    attribute = termios.tcgetattr(sys.stdin)
    tty.setcbreak(sys.stdin)
    try:
        while True:
            char = sys.stdin.read(1)
            if char == 'y' or char == 'Y':
                result = 'y'
                break
            elif char == 'n' or char == 'N':
                result = 'n'
                break
    except KeyboardInterrupt:
        result = '^C'
    termios.tcsetattr(sys.stdin, termios.TCSAFLUSH, attribute)
    print(result)
    return result
   

#===== ファイル削除 =====================================================  
def delete_file(target):
    ret = os.path.exists(target)
    try:
        if ret:
            os.remove(target)
        return True
    except:
        print('  >>> ' + target + ' を削除出来ませんでした。')
        return False
       
       
       
_target_user = ''
_num = raw_input('暗号化 or 復号化を選択してください。\n  1: 暗号化\n  2: 復号化\n  ※番号を入力してください。: ')

if _num != '1' and _num != '2':
    print(' >>> キャンセルしました。')
    sys.exit()
   
   
_keycode = getpass.getpass('  >>> キーコードを入力して下さい。: ')
if _keycode == '':
    sys.exit()
     
 
_message = '暗号化'  
  
if _num == '2':
    _message = '復号化' 
   
           
_source_file = raw_input('  >>> ' + _message + ' するファイル名を入力して下さい。: ')
if _source_file == '':
    sys.exit()
   

ret = os.path.exists(_source_file)
if not ret:
    print(_source_file + ' は存在しません。')
    sys.exit()
   
   
   
_dest_file = raw_input('  >>> 出力するファイル名を入力して下さい。(未入力可): ')
if _dest_file == '':
    _dest_file = _source_file + '.enc'
   

# 既存ファイルの存在と上書きの確認   
ret = os.path.exists(_dest_file)
if ret:
    result = yesno(' >>> ' + _dest_file + ' はすでに存在します、上書きしますか? (Yes or No) ')
   
    if result != 'y':
        print(' >>> 中止しました。')
        sys.exit()
       
         
result = yesno(' >>> ' + _message + ' を実行しますか? (Yes or No) ')
if result != 'y':
    print('  >>> キャンセルしました。')
    sys.exit()
                       

# 既存ファイル削除
ret = delete_file(_dest_file)
if not ret:
    print(' >>> ' + _dest_file + ' を削除できませんでした。 中止します。')
    sys.exit()

try:
    if _num == '1':
        encrypt_file(_keycode, _source_file, _dest_file) # 暗号化
    else:
        decrypt_file(_keycode, _source_file, _dest_file) # 復号化       
except Exception as e:
    print('  >>> Error 中止しました。 (02)' + e.message)
    sys.exit()
      
      
ret = os.path.exists(_dest_file) # 暗号化・復号化ファイルが作成されたか確認
if not ret:
    print('  >>> Error 失敗しました。 (03)')
    sys.exit()

path = os.path.dirname(_dest_file) # ファイルのdirectory  
       
print(subprocess.check_output(['ls', '-l', path])) # 確認用 ls -l
         
print(' >>> ' + _message + ' Complete!! <<<')

# 2016/05/09_1
#===== END angoka.py =========================================================


※参考リンク

http://eli.thegreenplace.net/2010/06/25/aes-encryption-of-files-in-python-with-pycrypto
#===== BEGIN cAngo.py =========================================================
# encoding: utf-8
import os, random, struct
from Crypto.Cipher import AES


def encrypt_file(key, in_filename, out_filename=None, chunksize=64*1024):
    """ Encrypts a file using AES (CBC mode) with the
        given key.
   
        key:
            The encryption key - a string that must be
            either 16, 24 or 32 bytes long. Longer keys
            are more secure.
       
        in_filename:
            Name of the input file
       
        out_filename:
            If None, '<in_filename>.enc' will be used.
       
        chunksize:
            Sets the size of the chunk which the function
            uses to read and encrypt the file. Larger chunk
            sizes can be faster for some files and machines.
            chunksize must be divisible by 16.
    """
   
    if not out_filename:
        out_filename = in_filename + '.enc'
   
    if len(key) < 8:
        print('keyは8桁以上にして下さい。') # 安全のため8桁以上に
        return
       
  
    if len(key) % 16 != 0:
        key = key +  '=' * (16 - (len(key) % 16))
        #print(key)
                
    iv = ''.join(chr(random.randint(0, 0xFF)) for i in range(16))
    encryptor = AES.new(key, AES.MODE_CBC, iv)
    filesize = os.path.getsize(in_filename)

    with open(in_filename, 'rb') as infile:
        with open(out_filename, 'wb') as outfile:
            outfile.write(struct.pack('<Q', filesize))
            outfile.write(iv)
       
            while True:
                chunk = infile.read(chunksize)
                if len(chunk) == 0:
                    break
                elif len(chunk) % 16 != 0:
                    chunk += ' ' * (16 - len(chunk) % 16)
               
                outfile.write(encryptor.encrypt(chunk))
               
            
            
def decrypt_file(key, in_filename, out_filename=None, chunksize=24*1024):
    """ Decrypts a file using AES (CBC mode) with the
        given key. Parameters are similar to encrypt_file,
        with one difference: out_filename, if not supplied
        will be in_filename without its last extension
        (i.e. if in_filename is 'aaa.zip.enc' then
        out_filename will be 'aaa.zip')
    """
   
    if not out_filename:
        out_filename = os.path.splitext(in_filename)[0]
   
   
    if len(key) < 8:
        print('keyは8桁以上にして下さい。') # 安全のため8桁以上に
        return
       
       
    # キーコードの文字数は16の倍数にする必要があるので足らない分は'='を付け足す   
    if len(key) % 16 != 0:
        key = key +  '=' * (16 - (len(key) % 16))
        #print(key)
       
       
    with open(in_filename, 'rb') as infile:
        origsize = struct.unpack('<Q', infile.read(struct.calcsize('Q')))[0]
        iv = infile.read(16)
        decryptor = AES.new(key, AES.MODE_CBC, iv)
   
        with open(out_filename, 'wb') as outfile:
            while True:
                chunk = infile.read(chunksize)
                if len(chunk) == 0:
                    break
                outfile.write(decryptor.decrypt(chunk))
           
            outfile.truncate(origsize)
           
               
# 2016/05/09_1
#===== END cAngo.py =========================================================


0 件のコメント:

コメントを投稿