2012-05-26 5 views
1

저는 Pyramid 1.3 (Python 2.7)을 사용하고 MySQL에 데이터를 저장하는 프로젝트를 진행하고 있습니다. 전자 메일 주소 테이블이 있는데 저장 용으로 암호화하고 싶습니다. 응용 프로그램에서 암호화하려고 시도하고보기 위해 암호를 해독합니다. 나는 완벽한 보안을 위해 노력하지 않을 것이지만 주로 데이터베이스 자체가 손상되어 데이터를 난독 화하는 것을 목표로하고 있습니다.Python AES 인코딩/디코딩 문자열 및 MySQL에 저장

저는 AES와 함께 PyCrypto를 사용하고 있으며 여기에있는 일부 게시물과 내가 찾은 웹 튜토리얼을 따르려고합니다. 지금까지 발견 된 가장 가까운 것이 this post이고 적어도 암호화하는 것으로 보인다. 나는 그것을 따라 데이터베이스에 저장된 "7hBAQrWhJRnL9YdBGJfRErGFwGi3aC6noGzYTrGwAoQ="과 같은 것을 얻는다. 그러나 해독 기능이 함께 erroring 유지 : 나는 일종의 내가 그것을 더 이해하지만 난 여전히 같은 오류가 계속 도움이 파이썬에 대한 몇 가지 유니 코드 프레젠테이션을 가로 질러왔다

UnicodeDecodeError: 'ascii' codec can't decode byte 0xa1 in position 1: ordinal not in range(128) 

.

인코딩, 데이터베이스 저장, 데이터베이스 풀 및 소스 데이터 문자열 디코딩 방법에 대한 간단한 자습서가 있습니까?

데이터베이스 열에 특정 데이터 정렬이 필요합니까? 필드가 특정 유형이어야합니까? 지금까지 기본 정렬을 사용하여 문자열을 저장한다고 가정하고 VARCHAR로 설정했습니다. 호환되지 않는 형식이나 뭔가 어딘가에서 인코딩 문제가있는 것처럼 들리지만 머리를 돌리면 뭔가를 변경해야합니다.

내가 제공 할 수있는 더 좋은 포인터가 있습니까? 내 코드는 기본적으로 위의 링크 사본을 보여줄 수 있습니다 ... 나는 단지 개념을 너무 많이 수정하기 전에 작동하는 증명을 얻으려고했습니다.

편집 : 일부 샘플 소스 ... MySQL의에서 는, 테이블 아이디 (INT) CLIENT_ID (INT) EMAILADDRESS VARCHAR (100) utf8mb4_general_ci (내가 가지고, 데이터 정렬과 주변 놀았 던입니다 그것이 있어야 무슨 생각)

파이썬!

from base64 import b64encode, b64decode, urlsafe_b64decode, urlsafe_b64encode 

BLOCK_SIZE = 32 
INTERRUPT = u'\u0001' 
PAD = u'\u0000' 
def AddPadding(data, interrupt, pad, block_size): 
    new_data = ''.join([data, interrupt]) 
    new_data_len = len(new_data) 
    remaining_len = block_size - new_data_len 
    to_pad_len = remaining_len % block_size 
    pad_string = pad * to_pad_len 
    return ''.join([new_data, pad_string]) 
def StripPadding(data, interrupt, pad): 
    return data.rstrip(pad).rstrip(interrupt)#data.rsplit(interrupt,1)[0]#rstrip(pad).rstrip(interrupt) 

SECRET_KEY = u'a1b2c3d4e5f6g7h8a1b2c3d4e5f6g7h8' 
IV = u'12345678abcdefgh' 

cipher_for_encryption = AES.new(SECRET_KEY, AES.MODE_CBC, IV) 
cipher_for_decryption = AES.new(SECRET_KEY, AES.MODE_CBC, IV) 

def EncryptWithAES(encrypt_cipher, plaintext_data): 
    plaintext_padded = AddPadding(plaintext_data, INTERRUPT, PAD, BLOCK_SIZE) 
    encrypted = encrypt_cipher.encrypt(plaintext_padded) 
    return urlsafe_b64encode(encrypted) 
def DecryptWithAES(decrypt_cipher, encrypted_data): 
    decoded_encrypted_data = urlsafe_b64decode(encrypted_data) 
    decrypted_data = decrypt_cipher.decrypt(decoded_encrypted_data) 
    return StripPadding(decrypted_data, INTERRUPT, PAD) 

#encrypts it 
posted_singleaddress = EncryptWithAES(cipher_for_encryption, posted_singleaddress) 

#"[email protected]" inserts "Ktpr49Uzn99HZXbmqEzGKlWo9wk-XBMXGZl_iyna-8c=" into the database 

clientemails은 위 표에서 이메일의 목록입니다. 밖으로 주석을 때 나는 오류를 얻을 :

#if clientemails: 
# decrypted = DecryptWithAES(cipher_for_decryption, clientemails[0].emailaddress) 

난 그냥 단지 시도하고이 일을 얻을 수있는 첫 번째 항목을 해독하려고 노력했지만 그게 지금에 맞는주는 것처럼 보이는 부분입니다 ....

+2

코드의 문제가있는 부분을 게시 할 수 있습니까? – Blender

+0

덧붙여서 편집 됨 ... –

+1

'AddPadding'과'StripPadding'가 예상대로 작동하는 것을 확인 했습니까? 두 번째로 "적합"을 정의하면 예외가 발생하거나 잘못된 데이터를 제공합니까? 예외가 발생하면 예외는 무엇입니까? 추적을 볼 수 있습니까? –

답변

2

PyCrypto의 일반적인 규칙은 암호화 키, IV, 일반 텍스트, 패딩 및 암호문을 항상 텍스트가 아닌 바이너리 문자열로 정의해야한다는 것입니다. 유니 코드를 사용하는 것은 그 자체로 문제의 원인입니다.

또 다른 문제점은 AES.new 키와 IV를 16 진수로 인코딩 된 형식으로 전달하므로 전자는 256 비트이고 후자는 128 비트입니다. 여전히 작동하는 것 같지만 128 비트 키가있는 AES128을 사용하는 것이 좋습니다. 따라서 이진으로 변환해야합니다 (예 : unhexlify). 두 개의 문자열 b'34 '는 단일 바이트'\ x34 '에 매핑됩니다. IV는 두 배가 길어야합니다.코드에서

이 가지고하는 것이 좋습니다 :

from binascii import unhexlify 

INTERRUPT = b'\x01' 
PAD = b'\x00' 
SECRET_KEY = unhexlify('a1b2c3d4e5f6g7h8a1b2c3d4e5f6g7h8') 
IV = unhexlify('12345678abcdefgh'*2) 

텍스트를 암호화해야하는 경우, 먼저 (예를 들어, UTF-8)를 인코딩 한 다음 기능 EncryptWithAES()에 전달한다. 또한 PyCrypto API 찍은 예제 참조 :

from Crypto.Cipher import AES 
from Crypto import Random 

key = b'Sixteen byte key' 
iv = Random.new().read(AES.block_size) 
cipher = AES.new(key, AES.MODE_CFB, iv) 
msg = iv + cipher.encrypt(b'Attack at dawn') 

암호화 단계의 결과 (즉 암호문이다) 진 스트링 다시이다. MySQL DB에 직접 저장하려면 BINARY 또는 VARBINARY 유형 열을 사용해야합니다.