Simple way to encode a string according to a passw

2019-01-01 15:06发布

Does Python have a built-in, simple way of encoding/decoding strings using a password?

Something like this:

>>> encode('John Doe', password = 'mypass')
'sjkl28cn2sx0'
>>> decode('sjkl28cn2sx0', password = 'mypass')
'John Doe'

So the string "John Doe" gets encrypted as 'sjkl28cn2sx0'. To get the original string, I would "unlock" that string with the key 'mypass', which is a password in my source code. I'd like this to be the way I can encrypt/decrypt a Word document with a password.

I would like to use these encrypted strings as URL parameters. My goal is obfuscation, not strong security; nothing mission critical is being encoded. I realize I could use a database table to store keys and values, but am trying to be minimalist.

15条回答
与君花间醉酒
2楼-- · 2019-01-01 15:17

Simple way is using the library, and PyCrypto is the good one.

查看更多
何处买醉
3楼-- · 2019-01-01 15:19

Here's a Python 3 version of the functions from @qneill 's answer:

import base64
def encode(key, clear):
    enc = []
    for i in range(len(clear)):
        key_c = key[i % len(key)]
        enc_c = chr((ord(clear[i]) + ord(key_c)) % 256)
        enc.append(enc_c)
    return base64.urlsafe_b64encode("".join(enc).encode()).decode()

def decode(key, enc):
    dec = []
    enc = base64.urlsafe_b64decode(enc).decode()
    for i in range(len(enc)):
        key_c = key[i % len(key)]
        dec_c = chr((256 + ord(enc[i]) - ord(key_c)) % 256)
        dec.append(dec_c)
    return "".join(dec)

The extra encode/decodes are needed because Python 3 has split strings/byte arrays into two different concepts, and updated their APIs to reflect that..

查看更多
零度萤火
4楼-- · 2019-01-01 15:22

As you explicitly state that you want obscurity not security, we'll avoid reprimanding you for the weakness of what you suggest :)

So, using PyCrypto:

from Crypto.Cipher import AES
import base64

msg_text = 'test some plain text here'.rjust(32)
secret_key = '1234567890123456' # create new & store somewhere safe

cipher = AES.new(secret_key,AES.MODE_ECB) # never use ECB in strong systems obviously
encoded = base64.b64encode(cipher.encrypt(msg_text))
# ...
decoded = cipher.decrypt(base64.b64decode(encoded))
print decoded.strip()

If someone gets a hold of your database and your code base, they will be able to decode the encrypted data. Keep your secret_key safe!

查看更多
姐姐魅力值爆表
5楼-- · 2019-01-01 15:22

Here's an implementation of URL Safe encryption and Decryption using AES(PyCrypto) and base64.

    import base64
    from Crypto import Random
    from Crypto.Cipher import AES

    AKEY = 'mysixteenbytekey' # AES key must be either 16, 24, or 32 bytes long

    iv = Random.new().read(AES.block_size)


    def encode(message):
        obj = AES.new(AKEY, AES.MODE_CFB, iv)
        return base64.urlsafe_b64encode(obj.encrypt(message))


    def decode(cipher):
        obj2 = AES.new(AKEY, AES.MODE_CFB, iv)
        return obj2.decrypt(base64.urlsafe_b64decode(cipher))

If you face some issue like this https://bugs.python.org/issue4329 ( TypeError: character mapping must return integer, None or unicode ) use str(cipher) while decoding as follows

return obj2.decrypt(base64.urlsafe_b64decode(str(cipher)))

    In [13]: encode("Hello World")
    Out[13]: b'67jjg-8_RyaJ-28='

    In [14]: %timeit encode("Hello World")
    100000 loops, best of 3: 13.9 µs per loop

    In [15]: decode(b'67jjg-8_RyaJ-28=')
    Out[15]: b'Hello World'

    In [16]: %timeit decode(b'67jjg-8_RyaJ-28=')
    100000 loops, best of 3: 15.2 µs per loop
查看更多
梦醉为红颜
6楼-- · 2019-01-01 15:25

This works but password length should be exactly 8. This is simple and requires pyDes.

from pyDes import *

def encode(data,password):
    k = des(password, CBC, "\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5)
    d = k.encrypt(data)
    return d

def decode(data,password):
    k = des(password, CBC, "\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5)
    d = k.decrypt(data)
    return d

x = encode('John Doe', 'mypass12')
y = decode(x,'mypass12')

print x
print y

OUTPUT:

³.\Þ\åS¾+æÅ`;Ê
John Doe
查看更多
无与为乐者.
7楼-- · 2019-01-01 15:28

As has been mentioned the PyCrypto library contains a suite of ciphers. The XOR cipher can be used to do the dirty work if you don't want to do it yourself:

from Crypto.Cipher import XOR
import base64

def encrypt(key, plaintext):
  cipher = XOR.new(key)
  return base64.b64encode(cipher.encrypt(plaintext))

def decrypt(key, ciphertext):
  cipher = XOR.new(key)
  return cipher.decrypt(base64.b64decode(ciphertext))

Even though it only provides minimal security I'd still recommend using a random looking key without any space characters (as XOR'ing an ASCII [a-zA-Z] character with a space just flips the case).

The cipher works as follows without having to pad the plaintext:

>>> encrypt('notsosecretkey', 'Attack at dawn!')
'LxsAEgwYRQIGRRAKEhdP'

>>> decrypt('notsosecretkey', encrypt('notsosecretkey', 'Attack at dawn!'))
'Attack at dawn!'

Credit to https://stackoverflow.com/a/2490376/241294 for the base64 encode/decode functions (I'm a python newbie).

查看更多
登录 后发表回答