How to realize this js encrypt script in python? - python-3.x

Recently I am doing something like auto-login with python, but i am a freshman in this area.
I want to login to www.jd.com, and after fetch the post data with Chrome, I found this
uuid:37ac1f08-0ed9-4e0d-a424-76c31d566915
eid:ZLTFMPUYPUVH3AQWGB3I4YEJ5YR4EQLSXV7YKAX27FNOY3CPTY37EVDW755A2DUGP6GKOFADCU7JKKYCAMYM3QHAS4
fp:b871dc2da5cf2bf85a6a5a56259e28e3
_t:_ntscXrr
loginType:f
loginname:xxxxxxx
nloginpwd:RAc2wPFCr7jwP5ocHh295pGBuZL9xUYzlWh108xqsp6o90x6KiHVTbw3Yn6NRz8YMDp%2BOHlT58oinO%2FuLwvysmD3XKazm0MYEulWseG2gotduYTywA6%2FrO1hUskfVjHuPoLu8r3stjNRQ0dnKF%2BvIxganMiDEUTiUmliAGQqnWc%3D
chkRememberMe:
authcode:
pubKey:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDC7kw8r6tq43pwApYvkJ5laljaN9BZb21TAIfT%2FvexbobzH7Q8SUdP5uDPXEBKzOjx2L28y7Xs1d9v3tdPfKI2LR7PAzWBmDMn8riHrDDNpUpJnlAGUqJG9ooPn8j7YNpcxCa1iybOlc2kEhmJn5uwoanQq%2BCA6agNkqly2H4j6wIDAQAB
sa_token:B68C442BE645754F33277E701208059007998C0A52BF7A8EAD6AD256C8D009D929F000C9DF4192A57234E3EA6F615E156C81EFA53D580517BB9357FB9516A01E25761124AE9AF7B3CFA3C38D38484A73343117232D8C7101034817F5DC7B6F52055B86745C3B42647752AEED916BA60EBBC84732E823766B234DC3A36C47691794488C0EAF9A459DC55C70B43B5F9AE3A233810AAC8D52FE65CB29B0C97A162039D4626DD8AFF4ECE8ABDB2411B3D4509C293CD344C3BAF14F059FF462D18C8761724FAF12E2BF3C590E14AE8198C7542C8A575F7FAD5B021BC1A4C852AB71E972157546E442CF0E9E7ABA667A02DD8386375595080A9E9A1B232DCE0944244FDC6AB4A499CC881E1BB8BA47831877F6AD6CF02FFF5671C60461E90517D1761B40FD6CA361677595F096C4E5250D72FDCC6E1FF89771AE1B0F1C89B7DCAFB88BD6F068F47850A7EBC747F35939552C7E32B28E6D347D5AEB78B9334779D4896431CCA166537C67690687B1DDA7CC9881914D2A9F25CAF2B80EB8E2D0DFED09EBB766287A6E34179DCC9530DF3D4FCD28C17845571E587FFA3FD0B69E3ACBC80FCBCE115EFD6CBC87BB8ED4D95AAAA680
seqSid:1777115819395099100
Here the password is encrypted, and later I found this js code
function getEntryptPwd(pwd){
var pubKey = $('#pubKey').val();
if(!pwd || !pubKey || !SysConfig.encryptInfo){
return pwd;
}
var encrypt = new JSEncrypt();
encrypt.setPublicKey(pubKey);
return encrypt.encrypt(pwd);
}
However, I don't know how to do the same thing in python, could anyone please tell me how to this?
Any suggestion would be greatly appreciated.

here is my way to encrypt the password using pubkey you get from the html.
Request the login url to get the pubkey (also other informations).
Install a third-party module rsa.
pip install rsa
Run the following script to encrypt your password based on pubkey.
And you can find my code here. :)
<input type="hidden" name="pubKey" id="pubKey" value="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDC7kw8r6tq43pwApYvkJ5laljaN9BZb21TAIfT/vexbobzH7Q8SUdP5uDPXEBKzOjx2L28y7Xs1d9v3tdPfKI2LR7PAzWBmDMn8riHrDDNpUpJnlAGUqJG9ooPn8j7YNpcxCa1iybOlc2kEhmJn5uwoanQq+CA6agNkqly2H4j6wIDAQAB" class="hide"/>
(admin) $ cat encrypt.py
import rsa
import base64
import os
def bytes2hex(s):
return s.decode()
def bytes2base64(s):
return bytes2hex(base64.standard_b64encode(s))
class RSA():
def __init__(self):
# self.pubkey = self.load_pub_key(pubkey) if pubkey else None
self.pubkey = None
pass
def form_pem_pub_key(self, keystr,):
"""
Fortmat a public key string to PEM format, in which start with
BEGIN PUBLIC KEY and end with END PUBLIC KEY.
Parameters:
keystr -- the public key string of PEM-encoded(base64)
Returns:
-- Formatted public key string
"""
import textwrap
line_len = 64
begin = ['-----BEGIN PUBLIC KEY-----']
end = ['-----END PUBLIC KEY-----']
return '\n'.join(begin + textwrap.wrap(keystr, line_len) + end)
def check_pem_key_str(self, keystr,):
return False
pass
def load_pem_pub_key(self, pubkey,):
if isinstance(pubkey, str):
keystr = pubkey if self.check_pem_key_str(pubkey) else self.form_pem_pub_key(pubkey)
self.pubkey = rsa.PublicKey.load_pkcs1_openssl_pem(keystr)
def encrypt(self, msg):
if not self.pubkey:
raise ValueError('Pubic key is empty, please load it first.')
# convert string or other type to bytes
msg = msg if isinstance(msg, bytes) else str(msg).encode()
return bytes2base64(rsa.encrypt(msg, self.pubkey))
def encrypt_password(pubkey, password):
rsa = RSA()
rsa.load_pem_pub_key(pubkey)
return rsa.encrypt(password)
password = 'test'
pubkey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDC7kw8r6tq43pwApYvkJ5laljaN9BZb21TAIfT/vexbobzH7Q8SUdP5uDPXEBKzOjx2L28y7Xs1d9v3tdPfKI2LR7PAzWBmDMn8riHrDDNpUpJnlAGUqJG9ooPn8j7YNpcxCa1iybOlc2kEhmJn5uwoanQq+CA6agNkqly2H4j6wIDAQAB'
print(encrypt_password(pubkey, password))
(admin) $ python encrypt.py
nQJvsRspY+zAnywU9YsSTNHb/OoNOLLbADsenBwOlDHnv//UUPpBidA4n4pN7Frm0iIRQAJT1hRNAu/tASZjihtWiOYuwD+XFos2Tmk+SLRIc6VvqvAL9CJFLrzbIS3tgbx9vkyM30Qy6ENFOyOcpR7nV93xY82F1dB7bRsuNGU=

Related

Python RSA key, recieved the key but getting error "This is not a private key"

code for cilent
import socket, json
from Cryptodome.Cipher import PKCS1_OAEP, PKCS1_v1_5
from Cryptodome.Random import get_random_bytes
from Cryptodome.PublicKey import RSA
def getnewsocket():
return socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsocket = getnewsocket()
clientsocket.connect(('localhost', 8089))
rsa_public = clientsocket.recv(99999)
encyrpted = clientsocket.recv(99999)
print(rsa_public)
rsakey = RSA.import_key(rsa_public.decode())
print(rsakey)
cipher = PKCS1_OAEP.new(rsakey)
decrypted = cipher.decrypt(encyrpted)
print(decrypted)
code for server
from Cryptodome.Cipher import PKCS1_OAEP, PKCS1_v1_5
from Cryptodome.Random import get_random_bytes
from Cryptodome.PublicKey import RSA
import socket
import json
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(('0.0.0.0', 8089)) # 0.0.0.0 is a special address
print("Server activated, waiting for client to connect")
serversocket.listen(5)
connection, address = serversocket.accept()
rsakey_pair=RSA.generate(2048)
rsa_private = rsakey_pair
rsa_public = rsakey_pair.publickey().export_key()
hi = b"this is a plain text"
print(rsa_public)
cipher = PKCS1_OAEP.new(rsa_private)
encyrpted = cipher.encrypt(hi)
connection.sendall(rsa_public)
connection.sendall(encyrpted)
tried alot of ways but is either getting bytes cannot be n or this is not a private key. Always unable to decrypt the content of ciper text at client. I guess the error is something related to socket only can send bytes, so when the key had send through the socket, although it is still in bytes but is a different kind of bytes
error :
File "C:\Users\shang\AppData\Local\Programs\Python\Python37-32\lib\site-packages\Cryptodome\Cipher\PKCS1_OAEP.py", line 171, in decrypt
m_int = self._key._decrypt(ct_int)
File "C:\Users\shang\AppData\Local\Programs\Python\Python37-32\lib\site-packages\Cryptodome\PublicKey\RSA.py", line 151, in _decrypt
raise TypeError("This is not a private key")
TypeError: This is not a private key
Well, yes, that's because it is a public key.
rsakey = RSA.import_key(rsa_public.decode())
cipher = PKCS1_OAEP.new(rsakey)
decrypted = cipher.decrypt(encyrpted)
It is not possible to encrypt with a private key by definition. Encryption is performed using the public key, decryption using the private key. Public and private keys are not interchangeable for RSA. Maybe you want to generate a signature instead?
The only reason why the encryption with the private key succeeds is that it is likely that it also contains the public exponent and therefore the public key. Of course, the public key doesn't contain the private key as that needs to be kept private.
Note that even if it would be secure to encrypt with a private key if both keys (and thus the modulus) are kept private then you might as well use symmetric encryption, e.g. using the hash over the modulus as AES key.

AWS Secrets Manager password issue in python3 and pystfp

Currently trying to connect sftp server using user credential from AWS secret manager, and password contains double quote special character, which causing the issue. Below is sample code,
import sys
import boto3
import base64
from botocore.exceptions import ClientError
import hashlib
import pysftp
secret_name = "SFTP_TEST"
region_name = "eu-central-1"
_SFTP_DETAILS = {}
pass1= "E?%/?s\"N1sS#OnXN"
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
cnopts.log = True
basepath ='/test/'
def get_connect(secret_name,region_name):
session = boto3.session.Session()
client = session.client(service_name='secretsmanager', region_name=region_name.strip())
if secret_name.strip() not in _SFTP_DETAILS:
try:
get_secret_value_response = client.get_secret_value(SecretId=secret_name.strip())
except Exception as e:
raise e
else:
if 'SecretString' in get_secret_value_response:
secret = get_secret_value_response['SecretString']
print("Secret value Original ==>",secret)
secretValue = json.loads(secret)
awsValue = secretValue.get(secret_name.strip())
sftpStrValue = awsValue.replace("“","\"").replace("”","\"")
print("Secrete Value After JSON loader ==>",sftpStrValue)
sftpValues = json.loads(sftpStrValue)
_HOST_NAME = sftpValues.get("url")
_USER_NAME = sftpValues.get("username")
_PASSWORD = sftpValues.get("password")
print("Secrete Password:::" + _PASSWORD)
_PORT = sftpValues.get("port")
with pysftp.Connection(_HOST_NAME, username=_USER_NAME, password=_PASSWORD, port=int('22'), cnopts=cnopts) as sftp:
print("I am in SFTP SERVER")
for attr in sftp.listdir_attr(basepath):
print("listdir is",attr)
_SFTP_DETAILS[secret_name] = [_HOST_NAME.strip(),_USER_NAME.strip(),_PASSWORD.strip(),_PORT.strip()]
return _SFTP_DETAILS[secret_name.strip()]
get_connect()
Here we are fetching password (_PASSWORD) from AWS secret manager and passing to pysftp.Connection function, but unable to connect.
Here if I am hard coded password i.e. pass1 in above code then its working fine and able connect. Unable to get the issue is from python or AWS Secrets Manager.
Could you please let me know why password from AWS secret manager is not working while hard coded is working correctly. Here requirement to keep password in AWS Secrets Manager.
Any help on this appreciated.
I have this as my secret in AWS Secret Manager Console:
Secret Key | Secret Value
TEST_KEY | afgvbq3tg"afsvgqag"af.qw/asffq3gvd13
If I get the secret_value by:
secret = client.get_secret_value(SecretId="test_secret_ron")
and print the secret["SecretString"], the result will look like:
'{"TEST_KEY":"afgvbq3tg\\"afsvgqag\\"af.qw/asffq3gvd13"}'
once you turn this string to dictionary by:
json.loads(secret["SecretString"])
the expected dictionary will reflect the correct format of the string:
{'TEST_KEY': 'afgvbq3tg"afsvgqag"af.qw/asffq3gvd13'}
enter image description here

Python smpplib truncating smpp credentials

I am using Python SMPP lib to send a SMS. When I try to connect to SmppServer with a longer credentials the username and password are getting truncated and authorisation is failing.
Auth failing case:
- Username/password longer than 16 char length
Passing case:
- Username/password not longer than 16 char
So because of the above observation I am sure there is no issue with the SMMPP gateway. The gateway I am trying to communicate itself accepts of username/password of any length.
The following is my code which wraps the smpplib in to a custom class:
import smpplib
import smpplib.gsm
from smpplib.client import Client
class SmppClientConfig(object, ):
def __init__(self, host, port, username, password, source, target, on_delivered_cb, on_sent_cb):
self.HOST = host
self.PORT = port
self.USERNAME = username
self.PASSWORD = password
self.SOURCE = source
self.TARGET = target
self.ON_RECEIVED_CALLBACK = on_sent_cb
self.ON_DELIVERED_CALLBACK = on_delivered_cb
class SmppSenderClient(object):
def __init__(self, config: SmppClientConfig):
print('Creating SMPP client config with host: ' + config.HOST + ' port: ' + str(config.PORT))
self._config = config
self._client = Client(config.HOST, config.PORT)
self._on_delivered_callback = config.ON_DELIVERED_CALLBACK
self._on_received_callback = config.ON_RECEIVED_CALLBACK
self._init_client()
def _init_client(self):
print('Initializing SmppSender client with username: ' + self._config.USERNAME)
self._register_events()
self._client.connect()
self._client.bind_transmitter(system_id=self._config.USERNAME, password=self._config.PASSWORD)
def _register_events(self):
print('Registering Smpp events')
self._client.set_message_sent_handler(self._config.ON_DELIVERED_CALLBACK)
self._client.set_message_received_handler(self._config.ON_RECEIVED_CALLBACK)
def send_message(self, message: str):
print('Sending SMS message to target: ' + self._config.TARGET)
parts, encoding_flag, msg_type_flag = smpplib.gsm.make_parts(message)
for part in parts:
self._client.send_message(
source_addr_ton=smpplib.consts.SMPP_TON_INTL,
source_addr_npi=smpplib.consts.SMPP_NPI_ISDN,
source_addr=self._config.SOURCE,
dest_addr_ton=smpplib.consts.SMPP_TON_INTL,
dest_addr_npi=smpplib.consts.SMPP_NPI_ISDN,
destination_addr=self._config.TARGET,
short_message=part,
data_coding=encoding_flag,
esm_class=msg_type_flag,
registered_delivery=True,
)
I am not sure if it's an expected behaviour of the library or a limitation. I have tried the find the documentation for this lib but could not find anything other than this.
Please advise if you experience a similar issue any work around possible or if this is expected behaviour in SMPP protocol (which very unlikely).
Update:
I found the limitation in the source code:
class BindTransmitter(Command):
"""Bind as a transmitter command"""
params = {
'system_id': Param(type=str, max=16),
'password': Param(type=str, max=9),
'system_type': Param(type=str, max=13),
'interface_version': Param(type=int, size=1),
'addr_ton': Param(type=int, size=1),
'addr_npi': Param(type=int, size=1),
'address_range': Param(type=str, max=41),
}
# Order is important, but params dictionary is unordered
params_order = (
'system_id', 'password', 'system_type',
'interface_version', 'addr_ton', 'addr_npi', 'address_range',
)
def __init__(self, command, **kwargs):
super(BindTransmitter, self).__init__(command, need_sequence=False, **kwargs)
self._set_vars(**(dict.fromkeys(self.params)))
self.interface_version = consts.SMPP_VERSION_34
As you can see the BindTransmitter contructor (__init__) truncates the system_id to a max length of 16 and passsword to 9. Not sure why this was done this way.
I checked the official SMPP protocol spec. According to the spec the system_id is supposed to max 16 and password is supposed to be 9 for connection type: transmitter.
The following is the screenshot of this spec:
This is the link to the spec if anyone is interested.
So in conclusion, the library implementation of the spec is correct.

How to fix "TypeError: Unicode-objects must be encoded before hashing" on bcrypt.hashpw

I am setting up a server, and on my login page I use bycrpt's hashpw function to hash the passwords before storing them in the database. When I click login, I get the error message "TypeError: Unicode-objects must be encoded before hashing" I have tried encoding the passwords before hashing them both with .encode() and .encdoe('utf-8') in multiple locations and times.
This is a copy of Windows Server 2019 (on an AWS EC2 instance), running Python 3.7 and Sqlite3. This was running fine for a while, and when I changed computers, it stopped working.
This is my code for the login page:
def loginpage():
global error
if request.method == "POST":
usrname = request.form['username']
pswd = request.form['password']
if not db.checkExists(usrname):
error = "Invalid username or password!"
elif not db.checkValidUser(usrname, pswd.encode('utf-8')):
error = "Invalid username or password!"
else:
session['loggedIn'] = True
session['user'] = request.form['username']
if session.get('prevurl') == None:
return redirect(url_for('index'))
else:
prev = session.get('prevurl')
session['prevurl'] = ''
return redirect(url_for(prev))
return render_template('login.html', **globals())
And this is my database handler code:
def checkValidUser(username, password):
#get salt and hash passwords
if not checkExists(username):
return False
salt = getSalt(username)
salt = salt[0][0]
#password = password.encode('utf-8')
password = bcrypt.hashpw(password, salt)
#connect to database
con = sql.connect(sqlite_db_file)
cur = con.cursor()
cur.execute("SELECT * FROM users WHERE username=? AND password=?", (username, password))
validUser = cur.fetchall()
con.close()
if not validUser:
return False
return True
When I click login, I should either see an error saying "Incorrect username or password" or get redirected to the main page while being logged in. Instead I get a typeError telling me that unicode objects must be encoded. If you know something that could help, I appreciate your help!
It could be that the issue is related to the differences between bcrypt and py-bcrypt as discussed here on github.
Those are different modules. bcrypt expects bytes (encoded strings), py-bcrypt expets strings (str). So if you don't want to change your code, you'd have to install py-bcrypt.
I'm not certain whether it has the same feature set.

Groovy script to decodebase64 and message digest SHA1. unable to run the script

I'm pretty new to Groovy scripts. I'm using script to perform decodebase64 on string and do Messagedigest SHA1 on the data. I had managed to get below code but its not working.
import java.security.*;
def Message processData(Message message) {
//Body
def body = message.getBody(String.class);
String decoded = body.bytes.decodeBase64().toVarchar();
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
byte[] digest = sha1.digest(decode.getBytes());
digest = new BigInteger(1, digest).toString(16);
message.setBody(digest);
return message;
}
Input would be:
kIAUQJVfhfLaTF2G4WouvCmZqA2zhFhujfqe3g1I4WBJobFrBWcXKG5XoPM1MQZF9UeoM0o99tf8FHVEkEIkN1s0Pw7vXyHurkbiY/Dic56Fqa+PovU9gU4US+oLHoEMSpoDMtrVtAskS0h6bCgv1Hph/1QHTlVeto/GIw0Obb9CtSqlfhoXL8ZqCBMlsWClF8q31PZaD4vt8ZRzjm/fnA1YsH8Fo5PfxdWFEVrsprvDyUHuRvr0CHbDyE7qszgYA+Ri0ylnulPEqOlsBvNpiXoiEtoOnFOjZrWmLCM6IjnR8b2efnTRQsELdYr3FjRbg1kLDz3xUDGBwTplF31CSw==
After decoding the input has unicode characters in it. I'm unable to get to it. After SHA1 the output would be of 40 char.
Can you guys please help.
Not sure what toVarchar() is doing, but I suspect it's at fault...
import java.security.MessageDigest
def msg = 'kIAUQJVfhfLaTF2G4WouvCmZqA2zhFhujfqe3g1I4WBJobFrBWcXKG5XoPM1MQZF9UeoM0o99tf8FHVEkEIkN1s0Pw7vXyHurkbiY/Dic56Fqa+PovU9gU4US+oLHoEMSpoDMtrVtAskS0h6bCgv1Hph/1QHTlVeto/GIw0Obb9CtSqlfhoXL8ZqCBMlsWClF8q31PZaD4vt8ZRzjm/fnA1YsH8Fo5PfxdWFEVrsprvDyUHuRvr0CHbDyE7qszgYA+Ri0ylnulPEqOlsBvNpiXoiEtoOnFOjZrWmLCM6IjnR8b2efnTRQsELdYr3FjRbg1kLDz3xUDGBwTplF31CSw=='
def digest = MessageDigest.getInstance('SHA1').digest(msg.decodeBase64())
def result = new BigInteger(1, digest).toString(16)
println result
Gives me
17a88df21eb9ad8669864f3ccdd435bfc1e054aa

Resources