Simple Way to Encode a String According to a Password

Simple way to encode a string according to a password?

Assuming you are only looking for simple obfuscation that will obscure things from the very casual observer, and you aren't looking to use third party libraries. I'd recommend something like the Vigenere cipher. It is one of the strongest of the simple ancient ciphers.

Vigenère cipher

It's quick and easy to implement. Something like:

import base64

def encode(key, string):
encoded_chars = []
for i in xrange(len(string)):
key_c = key[i % len(key)]
encoded_c = chr(ord(string[i]) + ord(key_c) % 256)
encoded_chars.append(encoded_c)
encoded_string = "".join(encoded_chars)
return base64.urlsafe_b64encode(encoded_string)

Decode is pretty much the same, except you subtract the key.

It is much harder to break if the strings you are encoding are short, and/or if it is hard to guess the length of the passphrase used.

If you are looking for something cryptographic, PyCrypto is probably your best bet, though previous answers overlook some details: ECB mode in PyCrypto requires your message to be a multiple of 16 characters in length. So, you must pad. Also, if you want to use them as URL parameters, use base64.urlsafe_b64_encode(), rather than the standard one. This replaces a few of the characters in the base64 alphabet with URL-safe characters (as it's name suggests).

However, you should be ABSOLUTELY certain that this very thin layer of obfuscation suffices for your needs before using this. The Wikipedia article I linked to provides detailed instructions for breaking the cipher, so anyone with a moderate amount of determination could easily break it.

Simple way to encode a string with a password in Nodejs?

Here is the solution, encode and decode with secret string.

 const encode = (secret, plaintext) => {
const enc = [];
for (let i = 0; i < plaintext.length; i += 1) {
const keyC = secret[i % secret.length];
const encC = `${String.fromCharCode((plaintext[i].charCodeAt(0) + keyC.charCodeAt(0)) % 256)}`;
enc.push(encC);
}
const str = enc.join('');
return Buffer.from(str, 'binary').toString('base64');
};

const decode = (secret, ciphertext) => {
const dec = [];
const enc = Buffer.from(ciphertext, 'base64').toString('binary');
for (let i = 0; i < enc.length; i += 1) {
const keyC = secret[i % secret.length];
const decC = `${String.fromCharCode((256 + enc[i].charCodeAt(0) - keyC.charCodeAt(0)) % 256)}`;
dec.push(decC);
}
return dec.join('');
};

console.log('result encode:', encode('abcd56&r#iu)=', '122411353520'));
console.log('result decode:', decode('abcd56&r#iu)=', 'kpSVmGZnWadWnqdZ'));

How to encrypt text with a password in python?

Here's how to do it properly in CBC mode, including PKCS#7 padding:

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

def encrypt(key, source, encode=True):
key = SHA256.new(key).digest() # use SHA-256 over our key to get a proper-sized AES key
IV = Random.new().read(AES.block_size) # generate IV
encryptor = AES.new(key, AES.MODE_CBC, IV)
padding = AES.block_size - len(source) % AES.block_size # calculate needed padding
source += bytes([padding]) * padding # Python 2.x: source += chr(padding) * padding
data = IV + encryptor.encrypt(source) # store the IV at the beginning and encrypt
return base64.b64encode(data).decode("latin-1") if encode else data

def decrypt(key, source, decode=True):
if decode:
source = base64.b64decode(source.encode("latin-1"))
key = SHA256.new(key).digest() # use SHA-256 over our key to get a proper-sized AES key
IV = source[:AES.block_size] # extract the IV from the beginning
decryptor = AES.new(key, AES.MODE_CBC, IV)
data = decryptor.decrypt(source[AES.block_size:]) # decrypt
padding = data[-1] # pick the padding value from the end; Python 2.x: ord(data[-1])
if data[-padding:] != bytes([padding]) * padding: # Python 2.x: chr(padding) * padding
raise ValueError("Invalid padding...")
return data[:-padding] # remove the padding

It's set to work with bytes data, so if you want to encrypt strings or use string passwords make sure you encode() them with a proper codec before passing them to the methods. If you leave the encode parameter to True the encrypt() output will be base64 encoded string, and decrypt() source should be also base64 string.

Now if you test it as:

my_password = b"secret_AES_key_string_to_encrypt/decrypt_with"
my_data = b"input_string_to_encrypt/decrypt"

print("key: {}".format(my_password))
print("data: {}".format(my_data))
encrypted = encrypt(my_password, my_data)
print("\nenc: {}".format(encrypted))
decrypted = decrypt(my_password, encrypted)
print("dec: {}".format(decrypted))
print("\ndata match: {}".format(my_data == decrypted))
print("\nSecond round....")
encrypted = encrypt(my_password, my_data)
print("\nenc: {}".format(encrypted))
decrypted = decrypt(my_password, encrypted)
print("dec: {}".format(decrypted))
print("\ndata match: {}".format(my_data == decrypted))

your output would be similar to:

key:  b'secret_AES_key_string_to_encrypt/decrypt_with'
data: b'input_string_to_encrypt/decrypt'

enc: 7roSO+P/4eYdyhCbZmraVfc305g5P8VhDBOUDGrXmHw8h5ISsS3aPTGfsTSqn9f5
dec: b'input_string_to_encrypt/decrypt'

data match: True

Second round....

enc: BQm8FeoPx1H+bztlZJYZH9foI+IKAorCXRsMjbiYQkqLWbGU3NU50OsR+L9Nuqm6
dec: b'input_string_to_encrypt/decrypt'

data match: True

Proving that same key and same data still produce different ciphertext each time.

Now, this is much better than ECB but... if you're going to use this for communication - don't! This is more to explain how it should be constructed, not really to be used in a production environment and especially not for communication as its missing a crucial ingredient - message authentication. Feel free to play with it, but you should not roll your own crypto, there are well vetted protocols that will help you avoid the common pitfalls and you should use those.

Do I need to include -n option when encoding a password using base64?

When you use an online converter to decode it to hex, you'll see that the first string becomes 6368616e67656d650a and has 0a (ASCII Linefeed) on the end, which the second doesn't have.

So the answer is yes, you really need to add the -n option.

If you change your echo to echo -n you'll see this as well.

echo -n Y2hhbmdlbWU= | base64 -d
changemePROMPT-SHOWS-HERE

Another way to see this is using the following UNIX command:

echo -n Y2hhbmdlbWUK | base64 -d | od -c
0000000 c h a n g e m e \n

echo -n Y2hhbmdlbWU= | base64 -d | od -c
0000000 c h a n g e m e

Where you can see the first encoding includes the linefeed and the second does not.

Encrypt a string with a password in ruby

You can use the encrypted_strings gem:

data = 'Whackabad'
password = 'Holycrap'
encrypted = data.encrypt(:symmetric, :algorithm => 'des-ecb', :password => password)
# => "N6gLAAL9d9lRjHUbh54Ctw==\n"

encrypted.decrypt(:symmetric, :algorithm => 'des-ecb', :password => password)
# => "Whackabad"

This solution does not encrypt nor store the password anywhere - it encrypts that data, and only someone who knows the password will be able to decrypt the data.

This is a good solution if you don't want anyone (including the admin of the site) to be able to decrypt the data without having the correct password.



Related Topics



Leave a reply



Submit