I have a PythonNet C# bytes[] object and I need to convert it to Python's bytes.
Is there a way to do this using Python?
Here is what I'm doing to get the bytes. I need to go into the winstore's credential store and export out a client certificate.
import clr, os
import requests
from cryptography.hazmat.primitives.serialization.pkcs12 import (
load_key_and_certificates,
)
from cryptography.hazmat.primitives.serialization import Encoding, NoEncryption
from cryptography.hazmat.backends import default_backend
clr.AddReference("System")
clr.AddReference("System.Security.Cryptography.X509Certificates")
clr.AddReference("System.Security.Cryptography")
from System.Security.Cryptography.X509Certificates import (
X509Store,
StoreName,
StoreLocation,
OpenFlags,
X509CertificateCollection,
X509FindType,
X509Certificate2,
X509ContentType,
)
store = X509Store(StoreName.My, StoreLocation.CurrentUser)
store.Open(OpenFlags.ReadOnly)
serial_number = (
'SUPER SECRET SERIAL NUMBER'
)
collection = store.Certificates.Find(
X509FindType.FindBySerialNumber, serial_number, False
)
cert = collection.get_Item(0)
pkcs12 = cert.Export(X509ContentType.Pkcs12, "<Secret Password>")
# I have System.Bytes[] need python bytes to use with pyopenssl/cryptography
This code is using the pythonnet library to access the crypto API on windows. It then dumps a client certificate, found by a serial number, to bytes. When the clr library returns the value, it's a system.Bytes[]. This is incompatible with other libraries, so I need a way to convert this object to Python bytes.
You should be able to use the Python function bytes (as #JabberJabber mentioned). The following works for me (c_sharp_bytes actually being the result of a C# function) with Python 3.8:
from System import Byte, Array
python_bytes = b'Some bytes'
# Python -> C#
c_sharp_bytes = Array[Byte](python_bytes) # <System.Byte[] object at 0x000001A33CC2A3D0>
# C# -> Python
python_bytes = bytes(c_sharp_bytes) # b'Some bytes'
Related
I've been trying to figure out how to use HMAC to hash a string in Python for a TOTP generator I've already made in PHP. In PHP, I use the command echo -n "0x00000000035362f9" | xxd -r -p | openssl dgst -sha1 -mac HMAC -macopt hexkey:0080700040024c8581c2 which returns the desired value 7289e7b135d54b86a462a53da93ef6ad28b902f8. However, when I use the hmac library in Python 3.10
from hashlib import sha1
from hmac import new
key = "00000000035362f9"
msg = "0080700040024c8581c2"
byte_key = bytes(key, "UTF-8")
message = msg.encode()
print(new(byte_key, message, sha1).hexdigest())
print(new(message, byte_key, sha1).hexdigest())
The printed values are b05fe172b6a8a20767c18e1bfba159f0ea54c2bd and 0fe109b32b17aeff840255558e6b5c8ff3d8a115, neither match what I want.
I've tried making the key and message hex values first, I've made them raw bytes using b'0080700040024c8581c2', encoding them using UTF-8 and ASCII, and none of the solutions have worked.
I've looked at other post relating to this, and none of them worked.
Python hmac (sha1) calculation
Python HMAC OpenSSL equivalent
hmac returning different hexdigest values to openssl
Why Python and Node.js's HMAC result is different in this code?
Implementing SHA1-HMAC with Python
#jasonharper's answer from the comments was correct.
from hashlib import sha1
from hmac import new
from binascii import unhexlify
msg = unhexlify("00000000035362f9")
key = unhexlify("0080700040024c8581c2")
print(new(key, msg, sha1).hexdigest())
I'm using the python hashlib to get a condensed sha256 value using the following command, can someone help me out with a compatible function?
import hashlib
biz_number = "000-00-00000"
total_amount = "45000"
external_auth_key = "00000000-0000-0000-0000-000000000000"
signature = hashlib.sha256(':'.join([biz_number, external_auth_key, total_amount]).encode()).hexdigest()
print(signature)
> b9c4510deb7e279687bac8503d12f0878e0955a0f247b9257cb600df10378895
I'm trying to encode the contents of a Python script in Linux. I just started off with a simple script called test.py -
# !/app/logs/Python/bin/python3
# -*- coding: ascii -*-
print ("hi")
Once I have the script, I execute the vim -x test.py and enter the encryption key twice. Then save the file as normal and then execute the script using python test.py
I tried almost all the examples provided in the link here but still i end up getting the below error -
SyntaxError: Non-ASCII character '\x97' in file test.py on line 1, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
I checked the default encoding using print sys.getdefaultencoding() and it is acsii.
What am i missing here. kindly clarify. I know this question is a duplicate but none of the solutions helped.
Python knows how to execute clear text Python source code. If you encrypt the source file, it no longer contains valid Python source and cannot be directly executed.
There are 2 possible ways here. First is to only obfuscate your source. You should be aware that obfuscation is not security, and a user could recover some Python source with some work (not necessarily the original source, because comments and doc strings could have been stripped off and variable names could have been changed). You could read How do I protect Python code? and google for python obfuscate to find some possible ways of obfuscating Python source and their trade-offs.
The good news with obfuscated source is that it can be used by anybody without any password.
Second way is to encrypt the source. If you use a decent tool, you can assume that it will be impossible to read or execute the file without knowing the key. In that sense, vim crypto has not the highest possible reputation. In the simplest way (for example with your example vim -x) you will have to decrypt the file to execute it. Unfortunately, good crypto modules are not shipped in a standard Python installation and must be downloaded from pypi. Well known crypto modules include pycrypto and cryptography.
You can then encrypt the most part of the code, and then at run time ask for the key, decrypt it and execute it. Still a serious job but feasible.
Alternatively, you could build in another language (C/C++) a decryptor that decrypts the remaining of the file and feed it into a python interpretor, but functionally, this is only a variant of the above method.
As per your comment I assume that you want to encrypt the source code and decrypt it (with the password) at run time. The princips are:
build a Python script that will take another arbitrary Python script, encode it with a secure crypto module and prepend it with some decrypting code.
at run time, the prepended code will ask for the password, decrypt the encrypted code exec it
The builder could be (this code uses the cryptography module):
import cryptography.fernet
import cryptography.hazmat.primitives.kdf.pbkdf2
import cryptography.hazmat.primitives.hashes
import cryptography.hazmat.backends
import base64
import os
import sys
# the encryption function
def encrypt_source(infile, outfile, passwd):
with open(infile, 'rb') as fdin: # read original file
plain_data = fdin.read()
salt, key = gen_key(passwd) # derive a key from the password
f = cryptography.fernet.Fernet(key)
crypted_data = f.encrypt(plain_data) # encrypt the original code
with open(outfile, "w") as fdout: # prepend a decoding block
fdout.write("""#! /usr/bin/env python
import cryptography.fernet
import cryptography.hazmat.primitives.kdf.pbkdf2
import cryptography.hazmat.primitives.hashes
import cryptography.hazmat.backends
import base64
import os
def gen_key(passwd, salt): # key derivation
kdf = cryptography.hazmat.primitives.kdf.pbkdf2.PBKDF2HMAC(
algorithm = cryptography.hazmat.primitives.hashes.SHA256(),
length = 32,
salt = salt,
iterations = 100000,
backend = cryptography.hazmat.backends.default_backend()
)
return base64.urlsafe_b64encode(kdf.derive(passwd))
passwd = input("Password:") # ask for the password
salt = base64.decodebytes({})
key = gen_key(passwd.encode(), salt) # derive the key from the password and the original salt
crypted_source = base64.decodebytes( # decode (base64) the crypted source
b'''{}'''
)
f = cryptography.fernet.Fernet(key)
plain_source = f.decrypt(crypted_source) # decrypt it
exec(plain_source) # and exec it
""".format(base64.encodebytes(salt),
base64.encodebytes(crypted_data).decode()))
# derive a key from a password and a random salt
def gen_key(passwd, salt=None):
if salt is None: salt = os.urandom(16)
kdf = cryptography.hazmat.primitives.kdf.pbkdf2.PBKDF2HMAC(
algorithm = cryptography.hazmat.primitives.hashes.SHA256(),
length = 32,
salt = salt,
iterations = 100000,
backend = cryptography.hazmat.backends.default_backend()
)
return salt, base64.urlsafe_b64encode(kdf.derive(passwd))
if __name__ == '__main__':
if len(sys.argv) != 3:
print("Usage {} infile outfile".format(sys.argv[0]))
sys.exit(1)
passwd = input("Password:").encode() # ask for a password
encrypt_source(sys.argv[1], sys.argv[2], passwd) # and generates an encrypted Python script
I'm trying to compress and encode my string using gGIP in python 2.7, I'm able to do that in Python 3 but I'm not getting same output in Python 2.7 version code:
Python 3:
import sys
import redis
import io import StringIO
import gzip
redisConn = redis.StrictRedis(host="127.0.0.1", port=6379, db=0)
myValue = "This is test data"
result = gzip.compress(myValue.encode())
redisConn.set("myKey", result)
Python 2.7:
import sys
import redis
import StringIO
import gzip
redisConn = redis.StrictRedis(host="127.0.0.1", port=6379, db=0)
myValue = "This is test data"
out = StringIO.StringIO()
gzip_s = gzip.GzipFile(fileobj=out, mode="w")
result = gzip_s.write(myValue.encode())
redisConn.set("myKey", result)
But Python 2.7 version code is breaking I'm getting an error:
'int' object has no attribute 'encode'
Can someone please help what's the equivalent code of Python 2.7 - my Python 3 version is working as expected.
Thanks for your help in advance.
Python 2 doesn't make the distinction between strings and bytes (even if the gzip stream is open as binary like here). You can write strings in a binary stream without needing to encode it. It has some drawbacks but in your case just remove the .encode() call:
gzip_s.write(myValue)
for a Python 2/3 agnostic code, I would simply do:
if bytes is str:
# python 2, no need to do anything
pass
else:
# python 3+: encode string as bytes
myValue = myValue.encode()
gzip_s.write(myValue)
EDIT: since you seem to issue a command redisConn.set("myKey", result), don't forget to call:
gzip_s.close()
before that, or it's not guaranteed that the file is fully flushed.
Here's a complete working example for Python 2.7. Note that gzip_s.write() returns the number of bytes written, so your code is passing an int to redisConn.set("myKey", result). Also, you probably should explicitly encode and decode the data to avoid unexpected encoding/decoding errors if you ever need to store non-ASCII data.
# -*- coding: utf-8 -*-
import redis
import StringIO
import gzip
redis_cxn = redis.StrictRedis(host='127.0.0.1', port=6379, db=0)
test_data = u'This is some test data with a non-ASCII character: ñ'
print 'Test data:\n ', test_data
out_file = StringIO.StringIO()
gzip_file = gzip.GzipFile(fileobj=out_file, mode='wb')
# If you don't encode the data yourself, it will be implicitly encoded as
# ASCII.
gzip_file.write(test_data.encode('utf-8'))
gzip_file.close()
# Get the bytes written to the underlying file object
value = out_file.getvalue()
print 'Setting value in Redis'
redis_cxn.set('key', value)
print 'Getting value from Redis'
retrieved_value = redis_cxn.get('key')
assert retrieved_value == value
in_file = StringIO.StringIO()
in_file.write(retrieved_value)
in_file.seek(0)
gzip_file = gzip.GzipFile(fileobj=in_file, mode='rb')
retrieved_data = gzip_file.read()
retrieved_data = retrieved_data.decode('utf-8')
gzip_file.close()
assert retrieved_data == test_data
print 'Data retrieved from Redis and unzippped:\n ', test_data
I want to decrypt response received from CCavenue.In their refrence code they use md5 library but for django 1.10 with python 3.6 not supported.
import md5
ModuleNotFoundError: No module named 'md5'
In python3.x,you should use this:
from hashlib import md5
You can now feed this object with bytes-like objects (normally
bytes) using the update() method.
e.g.
from hashlib import md5
m = md5()
m.update(b"Nobody")
print(m.hexdigest())
Module name: md5 .
Rationale: Replaced by the 'hashlib' module.
Date: 15-May-2007 .
Documentation: Documented as deprecated as of Python 2.5, but listing
in this PEP was neglected.DeprecationWarning raised as of Python 2.6.
See more details from hashlib.
Thanks to McGrady's answer.
Here is my detailed explanation:
Python 2.x
md5 is single module
not merged into hashlib
update() support str
not bytes
Special: for Python 2.7, md5 has merged to hashlib but update() still support str
code:
try:
import md5
except ImportError:
from hashlib import md5
def generateMd5(strToMd5) :
encrptedMd5 = ""
md5Instance = md5.new()
#<md5 HASH object # 0x1062af738>
md5Instance.update(strToMd5)
encrptedMd5 = md5Instance.hexdigest()
#af0230c7fcc75b34cbb268b9bf64da79
return encrptedMd5
Python 3.x
md5 has merged into hashlib
update() only support bytes
not support str
code:
from hashlib import md5 # only for python 3.x
def generateMd5(strToMd5) :
"""
generate md5 string from input string
eg:
xxxxxxxx -> af0230c7fcc75b34cbb268b9bf64da79
:param strToMd5: input string
:return: md5 string of 32 chars
"""
encrptedMd5 = ""
md5Instance = md5()
# print("type(md5Instance)=%s" % type(md5Instance)) # <class '_hashlib.HASH'>
# print("type(strToMd5)=%s" % type(strToMd5)) # <class 'str'>
bytesToMd5 = bytes(strToMd5, "UTF-8")
# print("type(bytesToMd5)=%s" % type(bytesToMd5)) # <class 'bytes'>
md5Instance.update(bytesToMd5)
encrptedMd5 = md5Instance.hexdigest()
# print("type(encrptedMd5)=%s" % type(encrptedMd5)) # <class 'str'>
# print("encrptedMd5=%s" % encrptedMd5) # 3a821616bec2e86e3e232d0c7f392cf5
return encrptedMd5