I am trying to encrypt the communications between a java and a python app and the problem is I'm getting different result in decrypting the encrypted string from the other side in both apps.
I searched a lot but I didn't found any problem in the code and I will be much appreciated if you guide me in this.
Here is the encryption function in java side:
public static String encrypt(String value) {
try {
String privateKey = "1234567887654321";
String stringIV = getRandomIV();
IvParameterSpec iv = new IvParameterSpec(stringIV.getBytes());
SecretKeySpec skeySpec = new SecretKeySpec(privateKey.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(value.getBytes(StandardCharsets.UTF_8));
String encryptedString = new String(encrypted)
String toEncrypt = stringIV + encryptedString;
return android.util.Base64.encodeToString(toEncrypt.getBytes("UTF-8"), android.util.Base64.DEFAULT);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
static String getRandomIV() {
UUID randomUUID = UUID.randomUUID();
return randomUUID.toString().replaceAll("_", "").replaceAll("-", "").substring(0,16);
}
and here is the decryption part in python:
msg_bytes=bytes(msg, encoding="utf8").decode("utf-8",'ignore')
b64decoded=base64.b64decode(msg_bytes)
cipher = AES.new('1234567887654321'.encode("utf8"), AES.MODE_CBC, b64decoded[0:16])
decoded = cipher.decrypt(b64decoded[16:48])
decoded = bytes(decoded).decode("utf-8",'ignore')
I'm testing this with a 32 byte message and I'm getting different results with AES part, alse here is my java decryption function:
public static String decrypt(String encrypted) {
try {
String privateKey = "1234567887654321";
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
byte[] base64decoded = new byte[0];
base64decoded = android.util.Base64.decode(encrypted, android.util.Base64.DEFAULT);
String base64decodedString = new String(base64decoded);
byte[] byteiv = Arrays.copyOfRange(base64decoded, 0, 16);
IvParameterSpec iv = new IvParameterSpec(byteiv);
SecretKeySpec skeySpec = new SecretKeySpec(privateKey.getBytes(), "AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] bytes = Hex.decodeHex(hex(base64decodedString.substring(16,48).getBytes()).toCharArray());
byte[] original = new byte[0];
byte[] bytemsg = Arrays.copyOfRange(base64decoded, 16, base64decoded.length);
original = cipher.doFinal(bytemsg);
return new String(original.toString());
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
and also python's encryption:
data = str(json.dumps(data))
iv = Random.get_random_bytes(16)
cipher = AES.new('1234567887654321'.encode("utf8"), AES.MODE_CBC, iv)
byte_iv = bytearray(iv)
encrypted = bytearray(cipher.encrypt(self.pad(data).encode("utf8")))
data = base64.b64encode(bytes(byte_iv + encrypted))
data = list(data)
data = bytes(data)
Any help will be much appreciated.
Related
I am trying to convert java code into python for doing some encryption using md5. Can you please help me to solve this.
public static void main(String args[]){
String result = "";
JSONObject o1 = new JSONObject();
o1.put("stationId","1298491919448667556");
String body = o1.toJSONString();
System.out.println(body);
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(body.getBytes());
byte[] b = md.digest();
result = java.util.Base64.getEncoder().encodeToString(b);
System.out.println("ContentMD5:"+result);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
Output: 5pxCd9dmyPR/V2jerFJdXQ==
Python code sample:
import json
import base64, hashlib
body_content = {}
body_content["stationId"] = "1298491919448667556"
body = json.dumps(body_content, sort_keys=True).encode()
hash = hashlib.md5()
hash.update(body)
content_md5 = base64.b64encode(hash.digest()).decode()
print("content-md5",content_md5)
Output: nc9o/UcyLURh7uEbz6A+8w==
Please help me to get same output as java.
How to convert below code in Python so that it gives same value on Windows even when executed multiple times.
Basically, it hashing password using sha512 and salt with 1000 iterations.
Here is the code:
using System;
using System.Security.Cryptography;
using System.Text;
namespace CheckHashing
{
class Program
{
protected static string CreateSHA512Hash(string Password, string Salt)
{
try
{
byte[] bytes_password = Encoding.UTF8.GetBytes(Password);
byte[] bytes_salt = Encoding.UTF8.GetBytes(Salt);
HashAlgorithm sha512hash = (HashAlgorithm)new SHA512CryptoServiceProvider();
for (int index = 0; index < 1000; ++index)
{
byte[] bytes_iteration = Encoding.UTF8.GetBytes(Convert.ToBase64String(bytes_password) + Convert.ToBase64String(bytes_salt));
bytes_password = sha512hash.ComputeHash(bytes_iteration);
}
return Convert.ToBase64String(bytes_password);
}
catch (Exception ex)
{
return "Exception"+ex.Message;
}
}
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
string hash_pwd = CreateSHA512Hash("Pass#21", "SALT(}");
Console.WriteLine(hash_pwd);
// Answer => HoCg9kKAl5WY0lWzvH7hdW+cTQGUfknALKDw49rvzUVUTt9X9fuggGpDIRfCdotR/kVU8m7gj2xzRzwIfDc5Xw==
}
}
}
Already tried below code which gives different values. Below output gives Invalid Password as error in the function.
import hashlib
from base64 import b64encode
password = "Pass#21"
salt = "SALT(}"
h = hashlib.pbkdf2_hmac('sha512', password.encode('utf-8'), salt.encode('utf-8'), 1000)
print(b64encode(h).decode())
# and below as well
hex_hash = hashlib.sha512(password.encode('utf-8') + salt.encode('utf-8')).digest()
for i in range(1000):
hex_hash = hashlib.sha512(hex_hash + salt.encode('utf-8')).digest()
print(b64encode(hex_hash).decode())
from passlib.hash import sha512_crypt as sha512
sha512_passwd = sha512.hash(password, rounds=1000)
print(sha512_passwd)
They don't start out the same.
If you add some prints to the C#
protected static string CreateSHA512Hash(string Password, string Salt)
{
try
{
byte[] bytes_password = Encoding.UTF8.GetBytes(Password);
byte[] bytes_salt = Encoding.UTF8.GetBytes(Salt);
HashAlgorithm sha512hash = (HashAlgorithm)new SHA512CryptoServiceProvider();
for (int index = 0; index < 1000; ++index)
{
if (index < 10)
Console.WriteLine(Convert.ToBase64String(bytes_password));
byte[] bytes_iteration = Encoding.UTF8.GetBytes(Convert.ToBase64String(bytes_password) + Convert.ToBase64String(bytes_salt));
bytes_password = sha512hash.ComputeHash(bytes_iteration);
}
Console.WriteLine("...");
return Convert.ToBase64String(bytes_password);
}
catch (Exception ex)
{
return "Exception" + ex.Message;
}
}
Here's my python port of the same code, with the same debug prints, so you can compare the first 10 values.
import hashlib
from base64 import b64encode
password = "Pass#21"
salt = "SALT(}"
bytes_password = password.encode('utf-8')
bytes_salt = salt.encode('utf-8')
for i in range(1000):
if i < 10:
print(b64encode(bytes_password).decode())
b64pw = b64encode(bytes_password).decode()
b64sa = b64encode(bytes_salt).decode()
bytes_iteration = (b64pw + b64sa).encode('utf-8')
bytes_password = hashlib.sha512(bytes_iteration).digest()
print('...')
print(b64encode(bytes_password).decode())
Your original code wasn't consistent on when it hex encoded and when it computed the hash, and it computed a hash prior to entering the loop.
This question is an evolution of this: Issue returning header byte from Python to Unity
Now the issue about header byte is solved, but I have a problem during the loop.
The data incoming good but after "n" times the loop break because receive a json string with an entire structure of data with open/close bracket PLUS the next structure of data with open bracket, some data and in the "image:" some data and many of the "\0" and unless the close bracket.. And the json parser obviously breaks. Why and what can I do? Thanks
Below the code revised:
IEnumerator Client()
{
while (!IsConnected(client))
{
try
{
client = new TcpClient(host, port);
s = client.GetStream();
byte[] byteBuffer = Encoding.UTF8.GetBytes("Connected to client");
s.Write(byteBuffer, 0, byteBuffer.Length);
while (true)
{
if (s.DataAvailable)
{
while (s.DataAvailable)
{
var header = new byte[4];
s.Read(header, 0, header.Length);
var fileSize = BitConverter.ToUInt32(header,0);
StringBuilder myCompleteMessage = new StringBuilder();
MemoryStream ms = new MemoryStream();
int increment = 0;
while (ms.Length < fileSize)
{
byte[] dataReceived = new byte[fileSize];
increment = s.Read(dataReceived, 0, dataReceived.Length);
ms.Write(dataReceived.Take(increment).ToArray(), 0, increment);
}
myCompleteMessage.AppendFormat("{0}", Encoding.UTF8.GetString(ms.GetBuffer()));
JSONNode data = JSONNode.Parse(myCompleteMessage.ToString());
....
// Do work with myCompleteMessage
yield return null;
}
}
}
}
}
}
I don't have your Unity environment here, so I can't have tested this.
Something like a loop (likely run in a coroutine or something that doesn't block Unity's default handling) like this should be enough to handle a stream of messages of the shape we established before (a 4-byte header signifying the message length, followed by that many bytes of JSON).
while (!IsConnected(client))
{
try
{
client = new TcpClient(host, port);
s = client.GetStream();
while (true)
{
var data = ReadPacket(s);
// Do work with data
}
}
}
ReadPacket should be something like
JSONNode ReadPacket(Stream s)
{
var buffer = new byte[131072];
// Read 4 bytes (we will assume we can always read that much)
var n = s.Read(buffer, 0, 4);
if(n < 4) throw new Exception("short read");
var fileSize = BitConverter.ToUInt32(buffer, 0);
Debug.Print("Reading a blob of length", fileSize);
// Memory stream to accumulate the reads into.
var ms = new MemoryStream();
while (ms.Length < fileSize)
{
// Figure out how much we can read -- if we're near the end,
// don't overread.
var maxRead = Math.Min(buffer.Length, fileSize - ms.Length);
var increment = s.Read(buffer, 0, maxRead);
// ... and write them into the stream.
ms.Write(buffer, 0, increment);
Debug.Print("Read", ms.Length, "of", fileSize);
}
// Decode the bytes to UTF-8 and parse.
return JSONNode.Parse(Encoding.UTF8.GetString(ms.GetBuffer()));
}
I have a wav file that I converted to binary and then changed it to base64 using C# and then post that base64 string to a python flask API so I can decode it and change back the base64 string to a wav file so I can save in a folder, I am getting this error below:
'utf-8' codec can't decode byte 0x80 in position 28: invalid start byte
Please see my code below:
public static void copy_to_watch_folder(string filepath, string filename)
{
try
{
AppDomain.CurrentDomain.SetPrincipalPolicy(System.Security.Principal.PrincipalPolicy.WindowsPrincipal);
var destinationFolder = SSKAccess.mapped_dir_path;
byte[] audio_file = File.ReadAllBytes(filepath);
var s = Convert.ToBase64String(audio_file);
string jsonData = JsonConvert.SerializeObject(new { Result = "OK", File = s, FileName = filename, token= SSKAccess.token }, Formatting.None);
StringContent sC2 = new StringContent(jsonData, System.Text.Encoding.UTF8, "application/json");
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.BaseAddress = new Uri(ConnectionSetup.connectionStr);
try
{
var response = client.PostAsync("putWavFile", sC2).Result;
if (response.IsSuccessStatusCode)
{
Logs.WriteToFile($"{ DateTime.Now } : {response.Content.ReadAsStringAsync()}");
}
}
catch (Exception exc)
{
Logs.WriteToFile($"HttpError : {exc.Message}");
}
//System.IO.File.Copy(filepath, $"{destinationFolder}{filename}", true);
}
catch (IOException copyError)
{
Logs.WriteToFile($"{DateTime.Now} - CopyError: {copyError.Message}");
}
}
My Python code looks like:
#app.route('/api/Call/putWavFile', methods=['POST'])
def PutWavFile():
if not request.json or not 'token' in request.json:
abort(400)
try:
filename = request.json['FileName']
binaryData = request.json['File']
file_decoded = base64.decodebytes(binaryData.encode('utf-8').strip())
_file = file_decoded.decode()
path_to_save = os.path.join(os.getcwd(), 'Watch', filename)
with open(path_to_save, mode='wb') as f:
f.write(file_decoded)
return jsonify({"FileCreated": "Success"})
except Exception as exc:
print(f"FileError: {str(exc)}")
return jsonify( {"Error": f"{str(exc)}"} )
Please assist and thanks in advance.
Thanks y'all for your assistance but finally I got the solution.
It turns out all I needed was the following line to decode the base64 string coming from my C# API call:
file_decoded = base64.b64decode(binaryData)
Thanks again for those who tried to assist.
I am new in python/django. I want to use AES Encryption.
after search I found some libraries like this: https://gist.github.com/jeetsukumaran/1291836
but I could not use them because of I have IV but this dont have IV code.
I have sample code in c#. any one may help me to convert this code to python code?
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.IO;
namespace AESUtility {
public class AES {
string AES_Key = string.Empty;
string AES_IV = string.Empty;
public AES(string AES_Key, string AES_IV) {
this.AES_Key = AES_Key;
this.AES_IV = AES_IV;
}
public bool Encrypt(String Input, out string encryptedString) {
try {
var aes = new RijndaelManaged();
aes.KeySize = 256;
aes.BlockSize = 256;
aes.Padding = PaddingMode.PKCS7;
aes.Key = Convert.FromBase64String(this.AES_Key);
aes.IV = Convert.FromBase64String(this.AES_IV);
var encrypt = aes.CreateEncryptor(aes.Key, aes.IV);
byte[] xBuff = null;
using(var ms = new MemoryStream()) {
using(var cs = new CryptoStream(ms, encrypt, CryptoStreamMode.Write)) {
byte[] xXml = Encoding.UTF8.GetBytes(Input);
cs.Write(xXml, 0, xXml.Length);
}
xBuff = ms.ToArray();
}
encryptedString = Convert.ToBase64String(xBuff);
return true;
} catch (Exception ex) {
encryptedString = string.Empty;
return false;
}
}
public bool Decrypt(String Input, out string decodedString) {
try {
RijndaelManaged aes = new RijndaelManaged();
aes.KeySize = 256;
aes.BlockSize = 256;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
aes.Key = Convert.FromBase64String(this.AES_Key);
aes.IV = Convert.FromBase64String(this.AES_IV);
var decrypt = aes.CreateDecryptor();
byte[] xBuff = null;
using(var ms = new MemoryStream()) {
using(var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write)) {
byte[] xXml = Convert.FromBase64String(Input);
cs.Write(xXml, 0, xXml.Length);
}
xBuff = ms.ToArray();
}
decodedString = Encoding.UTF8.GetString(xBuff);
return true;
} catch (Exception ex) {
decodedString = string.Empty;
return false;
}
}
}
}
EDIT 2022
pycrypto is now probably unmaintained. Latest release was in Oct 2013 (see https://pypi.org/project/pycrypto/#history)
In modern projects, use pycryptodome instead. The official documentation gives example of AES encryption: https://www.pycryptodome.org/en/latest/src/examples.html#encrypt-data-with-aes
Original answer:
Here is an example of AES encryption using well known pycrypto library:
>>> from Crypto.Cipher import AES
>>> obj = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
>>> message = "The answer is no"
>>> ciphertext = obj.encrypt(message)
>>> ciphertext
'\xd6\x83\x8dd!VT\x92\xaa`A\x05\xe0\x9b\x8b\xf1'
>>> obj2 = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
>>> obj2.decrypt(ciphertext)
'The answer is no'
AES 256 in OFB mode:
from Crypto.Cipher import AES
from Crypto.Random import new as Random
from hashlib import sha256
from base64 import b64encode,b64decode
class AESCipher:
def __init__(self,data,key):
self.block_size = 16
self.data = data
self.key = sha256(key.encode()).digest()[:32]
self.pad = lambda s: s + (self.block_size - len(s) % self.block_size) * chr (self.block_size - len(s) % self.block_size)
self.unpad = lambda s: s[:-ord(s[len(s) - 1:])]
def encrypt(self):
plain_text = self.pad(self.data)
iv = Random().read(AES.block_size)
cipher = AES.new(self.key,AES.MODE_OFB,iv)
return b64encode(iv + cipher.encrypt(plain_text.encode())).decode()
def decrypt(self):
cipher_text = b64decode(self.data.encode())
iv = cipher_text[:self.block_size]
cipher = AES.new(self.key,AES.MODE_OFB,iv)
return self.unpad(cipher.decrypt(cipher_text[self.block_size:])).decode()
Usage:
AESCipher("data to encrypt","key to use").encrypt()
AESCipher("encrypted data","key to use").decrypt()