I have an Api code from Python 2 is as below:
dataStr = request.POST['data']
data = json.loads(dataStr)
key_string = data.get('key')
seed = data.get('seed')
guid = data.get('guid')
sha1 = hashlib.sha1()
yesStr = seed + 'yes' + key_string + 'ke.yp.ad' + guid
sha1.update(yesStr)
yesValue = sha1.hexdigest()
resp = {
'data': yesValue,
'place_id': str(record.GroupNumber)
}
return HttpResponse(resp)
now I am upgrading it to python 3, but sha1.update must use an encoded string. but I don't know what the encoding format was. so far I tried
sha1.udpate(yesStr.encode("utf-8"))
sha1.udpate(yesStr.encode("ascii"))
but none of them is matching the old string. Can anyone help? thanks.
Finally I figured this out with my friend's help. The default encoding for Python 2 is 'latin1'. So what I did to fix the problem is to change
sha1.update(yesStr)
to:
sha1.update(yesStr.encode('latin1'))
and it worked in python 3.
Related
I need to pass two Python strings, representing an input file and an output file, to a C function named decrypt_file.
If I hardcode the string (for example, 'Test.OUT'), then it works. I don't know how to use a variable string. The C function returns a string with wrong characters.
int decrypt_file(char *inputfile, char *outputfile);
try:
file_name = bytes("example.txt", encoding='utf8')
p_file_name = ctypes.create_string_buffer(file_name, len(file_name))
so = "/home/hello/lib.so"
sodium = ctypes.CDLL(so)
sodium.strfry(p_file_name)
sodium.decrypt_file.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
sodium.decrypt_file(p_file_name, ctypes.c_char_p(b"Test.OUT"))
except Exception as e:
print(e)
return -> input file: mlxta.txeep
I use Linux and Pycharm terminal. Thanks for any tips.
ctypes was wrong. I don't know if this is the right way but it works.
filename = b"helloworld.txt"
so = "/home/lib.so"
sodium = ctypes.CDLL(so)
sodium.decrypt_file.argtypes = [ctypes.POINTER(ctypes.c_char), ctypes.c_char_p]
sodium.decrypt_file(filename, ctypes.c_char_p(b"Test.OUT"))
i try to encrypt the text with python and then i execute my code i get an error :
import base64
import boto3
from Crypto.Cipher import AES
PAD = lambda s: s + (32 - len(s) % 32) * ' '
def get_arn(aws_data):
return 'arn:aws:kms:{region}:{account_number}:key/{key_id}'.format(**aws_data)
def encrypt_data(aws_data, plaintext_message):
kms_client = boto3.client(
'kms',
region_name=aws_data['region'])
data_key = kms_client.generate_data_key(
KeyId=aws_data['key_id'],
KeySpec='AES_256')
cipher_text_blob = data_key.get('CiphertextBlob')
plaintext_key = data_key.get('Plaintext')
# Note, does not use IV or specify mode... for demo purposes only.
cypher = AES.new(plaintext_key, AES.MODE_ECB)
encrypted_data = base64.b64encode(cypher.encrypt(PAD(plaintext_message)))
# Need to preserve both of these data elements
return encrypted_data, cipher_text_blob
def main():
# Add your account number / region / KMS Key ID here.
aws_data = {
'region': 'eu-west-1',
'account_number': '701177775058',
'key_id': 'd67e033d-83ac-4b5e-93d4-aa6cdc3e292e',
}
# And your super secret message to envelope encrypt...
plaintext = PAD('Hello, World!')
# Store encrypted_data & cipher_text_blob in your persistent storage. You will need them both later.
encrypted_data, cipher_text_blob = encrypt_data(aws_data, plaintext)
print(encrypted_data)
if __name__ == '__main__':
main()
i Get : raise TypeError("Only byte strings can be passed to C code")
TypeError: Only byte strings can be passed to C code
Maybe whom know why? and how can i fix it ? please suggest!
Writing #Jeronimo's comment as an answer here, I was stuck with this same problem too and this helped.
Append a .encode("utf-8") to whatever you are passing to cypher.encrypt() function.
cypher.encrypt(PAD(plaintext_message).encode("utf-8"))
Note: this seems to be for python 3.x. For 2.x this same solution may not work.
A bit of a weird question perhaps, but I'm trying to replicate a python example where they are creating a HMAC SHA256 hash from a series of parameters.
I've run into a problem where I'm supposed to translate an api key in hex to ascii and use it as secret, but I just can't get the output to be the same as python.
>>> import hmac
>>> import hashlib
>>> apiKey = "76b02c0c4543a85e45552466694cf677937833c9cce87f0a628248af2d2c495b"
>>> apiKey.decode('hex')
'v\xb0,\x0cEC\xa8^EU$fiL\xf6w\x93x3\xc9\xcc\xe8\x7f\nb\x82H\xaf-,I['
If I've understood the material online this is supposed to represent the hex string in ascii characters.
Now to the powershell script:
$apikey = '76b02c0c4543a85e45552466694cf677937833c9cce87f0a628248af2d2c495b';
$hexstring = ""
for($i=0; $i -lt $apikey.Length;$i=$i+2){
$hexelement = [string]$apikey[$i] + [string]$apikey[$i+1]
$hexstring += [CHAR][BYTE][CONVERT]::toint16($hexelement,16)
}
That outputs the following:
v°,♀EC¨^EU$fiLöw?x3ÉÌè⌂
b?H¯-,I[
They are almost the same, but not quite and using them as secret in the HMAC generates different results. Any ideas?
Stating the obvious: The key in this example is no the real key.
Update:
They look more or less the same, but the encoding of the output is different. I also verified the hex to ASCII in multiple online functions and the powershell version seems right.
Does anyone have an idea how to compare the two different outputs?
Update 2:
I converted each character to integer and both Python and Powershell generates the same numbers, aka the content should be the same.
Attaching the scripts
Powershell:
Function generateToken {
Param($apikey, $url, $httpMethod, $queryparameters=$false, $postData=$false)
#$timestamp = [int]((Get-Date -UFormat %s).Replace(",", "."))
$timestamp = "1446128942"
$datastring = $httpMethod + $url
if($queryparameters){ $datastring += $queryparameters }
$datastring += $timestamp
if($postData){ $datastring += $postData }
$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
$apiAscii = HexToString -hexstring $apiKey
$hmacsha.key = [Text.Encoding]::ASCII.GetBytes($apiAscii)
$signature = $hmacsha.ComputeHash([Text.Encoding]::ASCII.GetBytes($datastring))
$signature
}
Function HexToString {
Param($hexstring)
$asciistring = ""
for($i=0; $i -lt $hexstring.Length;$i=$i+2){
$hexelement = [string]$hexstring[$i] + [string]$hexstring[$i+1]
$asciistring += [CHAR][BYTE][CONVERT]::toint16($hexelement,16)
}
$asciistring
}
Function TokenToHex {
Param([array]$Token)
$hexhash = ""
Foreach($element in $Token){
$hexhash += '{0:x}' -f $element
}
$hexhash
}
$apiEndpoint = "http://test.control.llnw.com/traffic-reporting-api/v1"
#what you see in Control on Edit My Profile page#
$apikey = '76b02c0c4543a85e45552466694cf677937833c9cce87f0a628248af2d2c495b';
$queryParameters = "shortname=bulkget&service=http&reportDuration=day&startDate=2012-01-01"
$postData = "{param1: 123, param2: 456}"
$token = generateToken -uri $apiEndpoint -httpMethod "GET" -queryparameters $queryParameters, postData=postData, -apiKey $apiKey
TokenToHex -Token $token
Python:
import hashlib
import hmac
import time
try: import simplejson as json
except ImportError: import json
class HMACSample:
def generateSecurityToken(self, url, httpMethod, apiKey, queryParameters=None, postData=None):
#timestamp = str(int(round(time.time()*1000)))
timestamp = "1446128942"
datastring = httpMethod + url
if queryParameters != None : datastring += queryParameters
datastring += timestamp
if postData != None : datastring += postData
token = hmac.new(apiKey.decode('hex'), msg=datastring, digestmod=hashlib.sha256).hexdigest()
return token
if __name__ == '__main__':
apiEndpoint = "http://test.control.llnw.com/traffic-reporting-api/v1"
#what you see in Control on Edit My Profile page#
apiKey = "76b02c0c4543a85e45552466694cf677937833c9cce87f0a628248af2d2c495b";
queryParameters = "shortname=bulkget&service=http&reportDuration=day&startDate=2012-01-01"
postData = "{param1: 123, param2: 456}"
tool = HMACSample()
hmac = tool.generateSecurityToken(url=apiEndpoint, httpMethod="GET", queryParameters=queryParameters, postData=postData, apiKey=apiKey)
print json.dumps(hmac, indent=4)
apiKey with "test" instead of the converted hex to ASCII string outputs the same value which made me suspect that the conversion was the problem. Now I'm not sure what to believe anymore.
/Patrik
ASCII encoding support characters from this code point range 0–127. Any character outside this range, encoded with byte 63, which correspond to ?, in case you decode byte array back to string. So, with your code, you ruin your key by applying ASCII encoding to it. But if what you want is a byte array, then why do you do Hex String -> ASCII String -> Byte Array instead of just Hex String -> Byte Array?
Here is PowerShell code, which generate same results, as your Python code:
function GenerateToken {
param($apikey, $url, $httpMethod, $queryparameters, $postData)
$datastring = -join #(
$httpMethod
$url
$queryparameters
#[DateTimeOffset]::Now.ToUnixTimeSeconds()
1446128942
$postData
)
$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha.Key = #($apikey -split '(?<=\G..)(?=.)'|ForEach-Object {[byte]::Parse($_,'HexNumber')})
[BitConverter]::ToString($hmacsha.ComputeHash([Text.Encoding]::UTF8.GetBytes($datastring))).Replace('-','').ToLower()
}
$apiEndpoint = "http://test.control.llnw.com/traffic-reporting-api/v1"
#what you see in Control on Edit My Profile page#
$apikey = '76b02c0c4543a85e45552466694cf677937833c9cce87f0a628248af2d2c495b';
$queryParameters = "shortname=bulkget&service=http&reportDuration=day&startDate=2012-01-01"
$postData = "{param1: 123, param2: 456}"
GenerateToken -url $apiEndpoint -httpMethod "GET" -queryparameters $queryParameters -postData $postData -apiKey $apiKey
I also fix some other errors in your PowerShell code. In particular, arguments to GenerateToken function call. Also, I change ASCII to UTF8 for $datastring encoding. UTF8 yields exactly same bytes if all characters are in ASCII range, so it does not matter in you case. But if you want to use characters out of ASCII range in $datastring, than you should choose same encoding, as you use in Python, or you will not get the same results.
What would be the Equivalent of following code in Python ?
More specifically looking for Equivalent of HttpEntity in Python. Rest of it I have it figured out. I am using the urllib2 python module.
String checkInUrl = serverURL+"resources/slmservices/fcs/commit";
URIBuilder checkInBuilder = new URIBuilder(checkInUrl.replace(" ", "%20"));
URI checkInUri = checkInBuilder.build();
checkinTicket = "sdfsfsdfsfsfweafdaewfw"
HttpEntity checkInReqEntitiy = new StringEntity(checkinTicket);
HttpRequestBasecheckInRequest=reMethod.getRequest(checkInUri,checkInReqEntitiy);
checkInRequest.addHeader("ticket", ticket);
HttpResponse checkInResponse = httpclient.execute(checkInRequest);
HttpEntity checkInResponseEntity = checkInResponse.getEntity();
StatusLine checkInResponseStatus = checkInResponse.getStatusLine();
It seems analogous to urllib2.Request:
https://docs.python.org/2/library/urllib2.html#urllib2.Request
I'm trying to get some results from UniProt, which is a protein database (details are not important). I'm trying to use some script that translates from one kind of ID to another. I was able to do this manually on the browser, but could not do it in Python.
In http://www.uniprot.org/faq/28 there are some sample scripts. I tried the Perl one and it seems to work, so the problem is my Python attempts. The (working) script is:
## tool_example.pl ##
use strict;
use warnings;
use LWP::UserAgent;
my $base = 'http://www.uniprot.org';
my $tool = 'mapping';
my $params = {
from => 'ACC', to => 'P_REFSEQ_AC', format => 'tab',
query => 'P13368 P20806 Q9UM73 P97793 Q17192'
};
my $agent = LWP::UserAgent->new;
push #{$agent->requests_redirectable}, 'POST';
print STDERR "Submitting...\n";
my $response = $agent->post("$base/$tool/", $params);
while (my $wait = $response->header('Retry-After')) {
print STDERR "Waiting ($wait)...\n";
sleep $wait;
print STDERR "Checking...\n";
$response = $agent->get($response->base);
}
$response->is_success ?
print $response->content :
die 'Failed, got ' . $response->status_line .
' for ' . $response->request->uri . "\n";
My questions are:
1) How would you do that in Python?
2) Will I be able to massively "scale" that (i.e., use a lot of entries in the query field)?
question #1:
This can be done using python's urllibs:
import urllib, urllib2
import time
import sys
query = ' '.join(sys.argv)
# encode params as a list of 2-tuples
params = ( ('from','ACC'), ('to', 'P_REFSEQ_AC'), ('format','tab'), ('query', query))
# url encode them
data = urllib.urlencode(params)
url = 'http://www.uniprot.org/mapping/'
# fetch the data
try:
foo = urllib2.urlopen(url, data)
except urllib2.HttpError, e:
if e.code == 503:
# blah blah get the value of the header...
wait_time = int(e.hdrs.get('Retry-after', 0))
print 'Sleeping %i seconds...' % (wait_time,)
time.sleep(wait_time)
foo = urllib2.urlopen(url, data)
# foo is a file-like object, do with it what you will.
foo.read()
You're probably better off using the Protein Identifier Cross Reference service from the EBI to convert one set of IDs to another. It has a very good REST interface.
http://www.ebi.ac.uk/Tools/picr/
I should also mention that UniProt has very good webservices available. Though if you are tied to using simple http requests for some reason then its probably not useful.
Let's assume that you are using Python 2.5.
We can use httplib to directly call the web site:
import httplib, urllib
querystring = {}
#Build the query string here from the following keys (query, format, columns, compress, limit, offset)
querystring["query"] = ""
querystring["format"] = "" # one of html | tab | fasta | gff | txt | xml | rdf | rss | list
querystring["columns"] = "" # the columns you want comma seperated
querystring["compress"] = "" # yes or no
## These may be optional
querystring["limit"] = "" # I guess if you only want a few rows
querystring["offset"] = "" # bring on paging
##From the examples - query=organism:9606+AND+antigen&format=xml&compress=no
##Delete the following and replace with your query
querystring = {}
querystring["query"] = "organism:9606 AND antigen"
querystring["format"] = "xml" #make it human readable
querystring["compress"] = "no" #I don't want to have to unzip
conn = httplib.HTTPConnection("www.uniprot.org")
conn.request("GET", "/uniprot/?"+ urllib.urlencode(querystring))
r1 = conn.getresponse()
if r1.status == 200:
data1 = r1.read()
print data1 #or do something with it
You could then make a function around creating the query string and you should be away.
check this out bioservices. they interface a lot of databases through Python.
https://pythonhosted.org/bioservices/_modules/bioservices/uniprot.html
conda install bioservices --yes
in complement to O.rka answer:
Question 1:
from bioservices import UniProt
u = UniProt()
res = u.get_df("P13368 P20806 Q9UM73 P97793 Q17192".split())
This returns a dataframe with all information about each entry.
Question 2: same answer. This should scale up.
Disclaimer: I'm the author of bioservices
There is a python package in pip which does exactly what you want
pip install uniprot-mapper