如果遇到问题可以留言,欢迎技术交流。交换意见
import subprocess
from functools import partial
subprocess.Popen = partial(subprocess.Popen, encoding='utf-8')
import execjs
print(execjs.get().name) # 获取js代码执行环境
res = execjs.eval(js) # 执行一段js代码
#先编译
jj = execjs.compile("""
function an(a, b){
return a + b
}
""")
# call() 运行代码中的xxx函数. 后续的参数是xxx的参数
ret = jj.call("an", 10, 20)
#读取js文件
f = open("01.js",mode="r",encoding="utf-8")
js_code = f.read()
# 执行js代码函数
js = execjs.compile(js_code)
js.call(函数)
obj = re.compile(r"window\._INIT_STATE__ = (?P.*?);",re.S) # 正则表达式
code = obj.search(js_code).group("code") #匹配正则表达式
print(type(code)) #这里的code是字符串
# execjs这个库会把运行的结果自动转化成对象
result = execjs.eval(code)# 拿到的是一个JS代码运行的结果
print(result) #是个字典,Python会自动转换成字典
print(type(result)) # dict
execjs._exceptions.ProgramError: Error: Malformed UTF-8 data
js报错了,返回的数据两端有引号或者双引号,需要去掉
function b(a, b) {
var c = CryptoJS.enc.Utf8.parse(b)
, d = CryptoJS.enc.Utf8.parse("0102030405060708")
, e = CryptoJS.enc.Utf8.parse(a)
, f = CryptoJS.AES.encrypt(e, c, {
iv: d,
mode: CryptoJS.mode.CBC
});
return f.toString()
}
#转换为UTF8
CryptoJS.enc.Utf8
# 转换为base64
CryptoJS.enc.Base64
from hashlib import md5
obj = md5()
obj.update("alex".encode("utf-8"))
# obj.update("wusir".encode('utf-8')) # 可以添加多个被加密的内容
bs = obj.hexdigest()
print(bs)
# 加盐
from hashlib import md5
salt = "我是盐.把我加进去就没人能破解了"
obj = md5(salt.encode("utf-8")) # 加盐
obj.update("alex".encode("utf-8"))
bs = obj.hexdigest()
print(bs)
sha1,sha256,sha512用法跟md5一样
from hashlib import sha1, sha256
sha = sha256(b'salt')
sha.update(b'alex')
print(sha.hexdigest())
from urllib.parse import quote, unquote, quote_plus, unquote_plus, urlencode
# 单独编码字符串 用 quote
wq = "米饭怎么吃"
print(quote(wq)) # %E7%B1%B3%E9%A5%AD%E6%80%8E%E4%B9%88%E5%90%83
print(quote(wq, encoding="gbk")) # %C3%D7%B7%B9%D4%F5%C3%B4%B3%D4
# 多个数据统一进行编码 用urlencode ,比如字典进行编码
dic = {
"wq": "米饭怎么吃",
"new_wq": "想怎么吃就怎么吃"
}
print(urlencode(dic)) # wq=%E7%B1%B3%E9%A5%AD%E6%80%8E%E4%B9%88%E5%90%83&new_wq=%E6%83%B3%E6%80%8E%E4%B9%88%E5%90%83%E5%B0%B1%E6%80%8E%E4%B9%88%E5%90%83
print(urlencode(dic, encoding="utf-8")) # 也可以指定字符集
# 一个完整的url编码过程
base_url = "http://www.baidu.com/s?"
params = {
"wd": "大王"
}
url = base_url + urlencode(params)
print(url) # http://www.baidu.com/s?wd=%E5%A4%A7%E7%8E%8B
#解码
s = "http://www.baidu.com/s?wd=%E5%A4%A7%E7%8E%8B"
print(unquote(s)) # http://www.baidu.com/s?wd=大王
print(quote("a /b/c=", safe="")) # 传递safe="" 可以保持和浏览器一致
print(quote_plus("a /b/c="))
import base64
bs = "我要吃饭".encode("utf-8")
# 把字节转化成b64
print(base64.b64encode(bs).decode())
# 把b64字符串转化成字节
s = "5oiR6KaB5ZCD6aWt"
print(base64.b64decode(s).decode("utf-8"))
#base64报错问题
import base64
s = "ztKwrsTj0b0"
bb = base64.b64decode(s)
print(bb)
此时运行出现以下问题
Traceback (most recent call last):
File "D:/PycharmProjects/rrrr.py", line 33, in
bb = base64.b64decode(s)
File "D:\Python38\lib\base64.py", line 87, in b64decode
return binascii.a2b_base64(s)
binascii.Error: Incorrect padding
# 解决办法
s = "ztKwrsTj0b0"
s += ("=" * (4 - len(s) % 4))
print("填充后", s)
bb = base64.b64decode(s).decode("gbk")
print(bb)
# 注意事项
由于标准的Base64编码后可能出现字符+和/,但是这两个字符在URL中就不能当做参数传递,所以就出现了Base64URL,下面是它们的区别:
1. Base64编码后出现的+和/在Base64URL会分别替换为-和_
2. Base64编码中末尾出现的=符号用于补位,这个字符和queryString中的key=value键值对会发生冲突,所以在Base64URL中=符号会被省略,去掉=后怎么解码呢?因为Base64是把3个字节变为4个字节,所以,Base64编码的长度永远是4的倍数,因此,需要加上=把Base64字符串的长度变为4的倍数,就可以正常解码了。
我们的应对方案:
在处理base64的时候.如果遇到了没有+和/的情况. 可以采用下面的方案来替换掉+和/
b64 = base64.b64decode(mi, b"-_")
# AES加密
from Crypto.Cipher import AES
import base64
"""
长度
16: *AES-128*
24: *AES-192*
32: *AES-256*
MODE 加密模式.常见的
ECB 可以没有iv
CBC 需要iv的
"""
# 创建加密器 注意秘钥和iv必须是16个字节
aes = AES.new( key= b"alexissbalexissb", mode=AES.MODE_CBC, iv=b"0102030405060708") # 分别是秘钥,模式,iv
data = "我吃饭了"
# 加密的内容必须是字节,所以先进行编码
data_bs = data.encode("utf-8")
# 需要加密的数据必须是16的倍数
# 填充规则: 缺少数据量的个数 * chr(缺少数据量个数)
pad_len = 16 - len(data_bs) % 16
data_bs += (pad_len * chr(pad_len)).encode("utf-8")
# 再对编码后的字节进行加密
bs = aes.encrypt(data_bs)
#用base64对结果进行编码
result = base64.b64encode(bs).decode()
用pad对字节进行填充达到规定的长度
# AES加密
from Crypto.Cipher import AES
import base64
from Crypto.Util.Padding import pad
"""
长度
16: *AES-128*
24: *AES-192*
32: *AES-256*
MODE 加密模式.常见的
ECB 可以没有iv
CBC 需要iv的
"""
# 创建加密器 注意秘钥和iv必须是16个字节
aes = AES.new( key= b"alexissbalexissb", mode=AES.MODE_CBC, iv=b"0102030405060708") # 分别是秘钥,模式,iv
data = "我吃饭了"
# 加密的内容必须是字节,所以先进行编码
data_bs = data.encode("utf-8")
# 需要加密的数据必须是16的倍数
# 用pad工具进行填充
data_bs = pad(data_bs,16)
# 再对编码后的字节进行加密
bs = aes.encrypt(data_bs)
#用base64对结果进行编码
result = base64.b64encode(bs).decode()
print(result)
# 转换成base64 bs是AES加密得到的字节
result = base64.b64encode(bs).decode()
#转换成16进制
import binascii
res = binascii.b2a_hex(bs).decode()
# 也可以转换成16进制,跟上面一个效果一样
bs.hex()
from Crypto.Util.Padding import pad,unpad
# base64编码后的密文
s = '9noPO0fcQizMbPkXcVOTDg=='
# 创建解密器
aes = AES.new(key= b"alexissbalexissb", mode=AES.MODE_CBC, iv=b"0102030405060708")
# 首先把base64编码转换成正常的字节
data = base64.b64decode(s)
res = aes.decrypt(data)
# 明文有可能有问题,因为字节是填充过得
# 用unpad 去除填充的内容,注:需要导入unpad
res = unpad(res,16)
# 得到明文
mingwen = res.decode("utf-8")
print(mingwen)
from Crypto.Cipher import DES
from Crypto.Util.Padding import pad,unpad
import base64
mingwen = '艾尼在学爬虫'
# DES key 是 8个字节
# iv 在CBC 模式下使用 长度8个字节
des = DES.new(key=b'aininora', mode=DES.MODE_CBC,iv=b'ainiaini')
# 明文进行编码
data = mingwen.encode('utf-8')
# 对编码后的字节进行填充
r = pad(data,8)
# 对填充后的字节进行des加密后的字节
res = des.encrypt(r)
# 对加密后的字节进行base64编码
base64_res = base64.b64encode(res).decode()
print(base64_res)
from Crypto.Cipher import DES
from Crypto.Util.Padding import pad,unpad
import base64
#base64密文
miwen = 't4TYyzRnIkmVmI81n+cdsVQfprHN5AtG'
#转换成base64字节
base64_byt = base64.b64decode(miwen)
# 创建解密器对象
des = DES.new(key=b'aininora', mode=DES.MODE_CBC,iv=b'ainiaini')
# 进行解密
r = des.decrypt(base64_byt)
# 得到的结果去掉填充部分
data = unpad(r,8)
# 对得到的字节进行解码
mingwen = data.decode('utf-8')
print(mingwen)
注:DES3 与AES,DES加密,解密规则一样,都是兄弟
注:js里的秘钥可以超过8位,js默认去前八位进行解密(JavaScript语言里)
setMaxDigits,
RSAKeyPair,
encryptedString
#生成和处理秘钥的
from Crypto.PublicKey import RSA
# 加密和解密
from Crypto.Cipher import PKCS1_v1_5
import base64
# 生成私钥
#bits = 2048 是秘钥的长度
rsa_key = RSA.generate(bits=2048)
# 把秘钥导出来
# 秘钥的本质是字节
# export_key 有个参数叫format,默认为PEM,背后的含义是把秘钥转换成了base64
key = rsa_key.export_key().decode()
with open('./rsa_miyao.pem',mode='w',encoding='utf-8') as f:
f.write(key)
# 把format换成DER,拿到的是字节
# key = rsa_key.export_key(format='DER')
# 把字节手动转换成base64
# result = base64.b64encode(key).decode()
#生成公钥
public_key = rsa_key.public_key()
# 把公钥导出来
p_key = public_key.export_key()
with open('./rsa_gongyao.pem',mode='wb') as f:
f.write(p_key)
#加密解密
from Crypto.Cipher import PKCS1_v1_5
#加载key
from Crypto.PublicKey import RSA
import base64
# 导入的key可以是PEM格式的秘钥,或者是直接形式的秘钥也可以
# 读取秘钥
f = open('./rsa_gongyao.pem',mode='r',encoding='utf-8')
# 拿到已经生成好的秘钥
pub_key = f.read()
f.close()
mingwen = "我要好好学习爬虫"
rsa_key = RSA.importKey(pub_key)
# 生成加密对象
rsa = PKCS1_v1_5.new(key=rsa_key)
# 对明文进行编码,处理成字节
mingwen_bs = mingwen.encode('utf-8')
# 对明文字节进行加密,得到密文字节
mi_bs = rsa.encrypt(mingwen_bs)
# 转换成base64
base_64 = base64.b64encode(mi_bs).decode()
#rsa每次加密后的结果可能不一样
print(base_64)
# 如果用了没有填充的算法,那每一次算出来的结果固定的
# 如果同一个明文反复计算结果是一样的那么考虑用js来完成逆向工作
// JSEncrypt
// setPublicKey
// 用的是固定的第三方库,库的名字叫jsencrypt
// 但是这个库只能在浏览器环境使用
// 我们用的是Node环境,所以不能直接是哟和
// 我们需要换一个库, 名字叫 node-jsencrypt
// 安装 npm install node-jsencrypt
var {JSEncrypto} = require('node-jsencrypt')
var o = new JSEncrypt
o.setPublicKey('xxxxxxxxxxxxxxxxxxxxxxxx')
r = o.encrypt("加密的内容")
// 可以直接把网站的内容拿过来
1,如果用了没有填充的算法,那每一次算出来的结果固定的
2,如果同一个明文反复计算结果是一样的那么考虑用js来完成逆向工作
// 特征:
// "010001" -> 这是16进制 -> 65537
// setMaxDigits
// RSAKeyPair
// encryptedString
const {
setMaxDigits,
RSAKeyPair,
encryptedString
} = require("./Ras加密");
function c(a,b,c){
var d,e;
return setMaxDigits(131),
d = new RSAKeyPair(b,"",c),
e = encryptedString(d,a)
}
注:./RSA加密 这个文件内容过长,如果需要请留言,我单独分享
例如:网易云案例
const CryptoJS = require("crypto-js")
var window = this
const {
setMaxDigits,
RSAKeyPair,
encryptedString
} = require("./Ras加密");
!function() {
function a(a) {
var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";
for (d = 0; a > d; d += 1)
e = Math.random() * b.length,
e = Math.floor(e),
c += b.charAt(e);
return c
}
function b(a, b) {
var c = CryptoJS.enc.Utf8.parse(b)
, d = CryptoJS.enc.Utf8.parse("0102030405060708")
, e = CryptoJS.enc.Utf8.parse(a)
, f = CryptoJS.AES.encrypt(e, c, {
iv: d,
mode: CryptoJS.mode.CBC
});
return f.toString()
}
function c(a, b, c) {
var d, e;
return setMaxDigits(131),
d = new RSAKeyPair(b,"",c),
e = encryptedString(d, a)
}
function d(d, e, f, g) {
var h = {}
, i = a(16);
return h.encText = b(d, g),
h.encText = b(h.encText, i),
h.encSecKey = c(i, e, f),
h
}
function e(a, b, d, e) {
var f = {};
return f.encText = c(a + e, b, d),
f
}
window.asrsea = d,
window.ecnonasr = e
}();
var params = {
csrf_token: "",
encodeType: "aac",
ids: "[1325905146]",
level: "standard"
}
var second = '010001'
var third = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'
var forth = '0CoJUm6Qyw8W8jud'
function fn(params) {
return window.asrsea(JSON.stringify(params),second,third,forth)
#加密解密
from Crypto.Cipher import PKCS1_v1_5
#加载key
from Crypto.PublicKey import RSA
import base64
f = open('./rsa_miyao.pem',mode='r',encoding='utf-8')
# 拿到已经生成好的秘钥
pri_key = f.read()
f.close()
# 拿到秘钥
rsakey = RSA.importKey(pri_key)
# 生成解密器对象
rsa = PKCS1_v1_5.new(key=rsakey)
miwen = 'mmf28CJEtFU2Y6C/qx10xoaRmsiY2at3LBjHR5DFdnG9V+5sGPFaMGDGM4OBVWKKJNuSFZgGL9Y409mbh32IKRL4TZYnc0RvJH/0t38d7AmnqnHAyTRUvpKlPzzJg559md6BcTA/ZpYZ4WAtXRuysMvuPTdlRvog2ceGJDXURajU3KyzHXFA9Hc+AamVL75D+YKrOB6n9YeV7n4+DK5mqouNlLp6Plee39vYBzN0IKkzyD6RatmVVUIxJCsUJmeJgIdnBGEuRA9bGNOG3VQa7NF/syWjiRNbKYz+KZHx+RtQ9GuzmPhtJbjh8anPeR2kzNwgfD1HiKhIBDQKVQH/eA=='
#对密文进行base64解码转换成字节
base64_2bs = base64.b64decode(miwen)
#对拿到的字节进行rsa解密得到明文字节
# 解密第二个参数给个None,意思是解密时出错了返回None
mingwen_bs = rsa.decrypt(base64_2bs,None)
#对明文字节进行解码得到明文
mingwen = mingwen_bs.decode('utf-8')
print(mingwen)
如果遇到问题可以留言,欢迎技术交流。交换意见