• 杂项之python利用pycrypto实现RSA


    杂项之python利用pycrypto实现RSA

    本节内容

    1. pycrypto模块简介
    2. RSA的公私钥生成
    3. RSA使用公钥加密数据
    4. RSA使用私钥解密密文
    5. 破解博客园登陆

    pycrypto模块简介

    pycrypto模块是python中用来处理加密解密等信息安全相关的一个很重要模块。

    该模块支持的加密方式:

    1. 对称加密方式:

      1. AES
      2. DES
      3. ARC4
    2. 散列值计算:

      1. MD5
      2. SHA
      3. HMAC
    3. 公钥加密和签名:

      1. RSA
      2. DSA

    基本上常见的关于信息安全类的算法都可以支持,所以,这是一个很强大的模块。

    安装方式:pip install pycrypto
    如果在windows上的python3.5中安装完成之后导入from Crypto import Random模块失败,需要找到python35安装目录下的Libsite-packagesCryptoRandomOSRNG t.py文件,将import winrandom修改成from . import winrandom

    关于加密方式的了解可以看我这边博客:加密方式介绍
    关于非对称加密算法(RSA)的使用可以看我这篇博客:数字签名和数字证书

    RSA的公私钥生成

    from Crypto import Random
    from Crypto.PublicKey import RSA
    
    
    # 伪随机数生成器
    random_generator = Random.new().read
    # rsa算法生成实例
    rsa = RSA.generate(1024, random_generator)
    
    # master的秘钥对的生成
    private_pem = rsa.exportKey()
    
    #--------------------------------------------生成公私钥对文件-----------------------------------------------------------
    with open('master-private.pem', 'wb') as f:
        f.write(private_pem)
    
    public_pem = rsa.publickey().exportKey()
    with open('master-public.pem', 'wb') as f:
        f.write(public_pem)
    
    #---------------------------------------------------
    # ghost的秘钥对的生成
    private_pem = rsa.exportKey()
    with open('ghost-private.pem', 'wb') as f:
        f.write(private_pem)
    
    public_pem = rsa.publickey().exportKey()
    with open('ghost-public.pem', 'wb') as f:
        f.write(public_pem)
    
    #-----------------------------------生成的公私钥文件类似于如下形式-------------------------------------------------------
    # 私钥
    -----BEGIN RSA PRIVATE KEY-----
    MIICXAIBAAKBgQC6mwuOxuqYi6mugLGr3OuiHwm/hF4kQX1zd5VhGwxYf4H5+pkO
    CES2UjOyLP9Xh6w+DJtRwTGE2xwDd3wMfW2wkHijM/uHkM9Jt+oRGIjy4IiXo+7t
    ue/NWBkDiQm1qte0YDKlmkFREwvZ5X2KaCsSx+dyKH4QsovxQ3/RxftdmQIDAQAB
    AoGAPA5SNe1G6zlnrsW0aL99Bnw+wuhy8/Av082Uwd/WpVTEHBPO1nlKw/LIuHtK
    4nzDrmSYSEOJEF0EMwltXwevGSm1wq2FBhX4T+kz3XUpWfv9O0dlHeNtgxeD1QXL
    kOxqU4F2WpdALgvi/rlPDd0aIagoXLi8MXkUH7hQlrJpQUECQQC6rygx3jDQA9Iw
    kPUXlokEuLod+Kgoa700S5qpJi7vft675+tMG5SZtr+HQeqGHty0fqc8MIcy1fJm
    ZYUrogN9AkEA/+RrrOoTYQbR3ENslTsNsiqQa2aZW5XAv9pEyGJBWu/4HUEEa6G3
    FY0Y3ACZR0Xaraya8XAgOo61pWm83GBlTQJBAKH2812Ikzr2BbdDHJExdoEVL8xu
    /p3LE6U6bt2QFiqNHPtT9C3cw+k0xyi3RJzGS9+A/uDWjYXKXvr92zMG5hUCQFXR
    alccTZF9swX2ysSlgGtfIP4T85ymdXUiI208noR79C8DbhMWsgsVPeASh1VC1Rrn
    xzLvkq9wyvSFqKQT5AUCQAxMO7KI1rwIm+ISuDEcwxRJXkdFypD74kOSYRxTqMun
    Zdu4ku4t6mVeq5kBv1/S2dtF3TiqMRlxmLmV/fx7KHM=
    -----END RSA PRIVATE KEY-----
    
    #公钥
    -----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6mwuOxuqYi6mugLGr3OuiHwm/
    hF4kQX1zd5VhGwxYf4H5+pkOCES2UjOyLP9Xh6w+DJtRwTGE2xwDd3wMfW2wkHij
    M/uHkM9Jt+oRGIjy4IiXo+7tue/NWBkDiQm1qte0YDKlmkFREwvZ5X2KaCsSx+dy
    KH4QsovxQ3/RxftdmQIDAQAB
    -----END PUBLIC KEY-----
    

    RSA使用公私钥加解密数据

    from Crypto.PublicKey import RSA
    from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
    import base64
    
    message = 'hello ghost, this is a plian text'
    with open('ghost-public.pem',"r") as f:
         key = f.read()
         rsakey = RSA.importKey(key)  # 导入读取到的公钥
         cipher = Cipher_pkcs1_v1_5.new(rsakey)  # 生成对象
         cipher_text = base64.b64encode(cipher.encrypt(message.encode(encoding="utf-8")))  # 通过生成的对象加密message明文,注意,在python3中加密的数据必须是bytes类型的数据,不能是str类型的数据
         print(cipher_text)
    
    with open('ghost-private.pem') as f:
        key = f.read()
        rsakey = RSA.importKey(key)  # 导入读取到的私钥
        cipher = Cipher_pkcs1_v1_5.new(rsakey)  # 生成对象
        text = cipher.decrypt(base64.b64decode(cipher_text), "ERROR")  # 将密文解密成明文,返回的是一个bytes类型数据,需要自己转换成str
        print(text)
    # 结果:
    b'meBtYXP35VNjtWXsONDluweXdG98tMHjb5GxBLFJ0GJzo+96wSrHe8SDhNJweDJP6/OdeIQ8jP1HKCK+aC9HA12YMSUUqcixsY5s8QUyTs+fkMjGrlC6I7hPLO4DGQbFXEY0jiqP9ycgmAi5FCsDMcm0oEm8/fVzv7vl9QarSN4='  # 加密后的密文
    b'hello ghost, this is a plian text'  # 解密后的明文
    

    破解博客园登陆

    经过分析博客园登陆方式为在用户填入用户名和密码之后,点击登录时js将会使用JSEncrypt这个开源组件对用户输入的用户名和密码进行加密,加密的公钥在js源码中查找到了,为”MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCp0wHYbg/NOPO3nzMD3dndwS0MccuMeXCHgVlGOoYyFwLdS24Im2e7YyhB0wrUsyYf0/nhzCzBK8ZC9eCWqd0aHbdgOQT6CuFQBMjbyGYvlVYU2ZP7kG9Ft6YV6oc9ambuO7nPZh+bvXH0zDKfi02prknrScAKC0XhadTHT3Al0QIDAQAB”

    后经查询资料得知该js组件使用的加密方式为RSA加密,又获取到了加密的公钥,所以,我们可以自己模拟JS加密方式将我们自己的用户名密码使用RSA加密之后提交到博客园服务器来实现登录。

    import re
    import json
    from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
    from Crypto.PublicKey import RSA
    import base64
    import requests
    
    def js_encrypt(text):
        # 通过拿到js中的RSA公钥,构造完整的公钥部分
        key = """-----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCp0wHYbg/NOPO3nzMD3dndwS0MccuMeXCHgVlGOoYyFwLdS24Im2e7YyhB0wrUsyYf0/nhzCzBK8ZC9eCWqd0aHbdgOQT6CuFQBMjbyGYvlVYU2ZP7kG9Ft6YV6oc9ambuO7nPZh+bvXH0zDKfi02prknrScAKC0XhadTHT3Al0QIDAQAB
    -----END PUBLIC KEY-----"""
    
        rsakey = RSA.importKey(key)
        cipher = Cipher_pkcs1_v1_5.new(rsakey)  # 生成对象
        cipher_text = base64.b64encode(cipher.encrypt(text.encode(encoding="utf-8")))  # 对传递进来的用户名或密码字符串加密
        print(cipher_text)
        value = cipher_text.decode('utf8')  # 将加密获取到的bytes类型密文解码成str类型
    
        return value
    
    session = requests.Session()
    
    i1 = session.get('https://passport.cnblogs.com/user/signin')  # 访问博客园登陆页面
    rep = re.compile("'VerificationToken': '(.*)'")  # 构造正则获取博客园的CSRF键值对
    v = re.search(rep, i1.text)
    verification_token = v.group(1)  # 拿到CSRF值
    
    form_data = {  # 构造post的请求体
        'input1': js_encrypt('你博客园账号'),  # 将用户名填在提示位置,将返回加密后的用户名
        'input2': js_encrypt('你博客园密码'),  # 将密码填在提示位置,将返回加密后的密码
        'remember': False
    }
    
    i2 = session.post(url='https://passport.cnblogs.com/user/signin',  # post访问登陆页面,发送登陆请求
                      data=json.dumps(form_data),
                      headers={
                          'Content-Type': 'application/json; charset=UTF-8',  # 设置Content-Type类型为JSON类型
                          'X-Requested-With': 'XMLHttpRequest',  # 设置头部的X-Requested-With字段,标示该请求为AJAX请求
                          'VerificationToken': verification_token}  # 将之前获取到的CSRF键值对设置在头部信息中
                      )
    
    i3 = session.get(url='https://i.cnblogs.com')  # 访问登陆后的页面
    
    print(i3.text)  # 如果打印出登陆后的页面,说明登陆操作成功
    
  • 相关阅读:
    JavaScript与OC的交互
    通过修改自动布局的约束实现键盘弹出后view上推
    Foundation框架之NSArray
    Foundation框架之NSString
    Foundation框架之常用结构体
    C语言中的预处理指令
    C语言指针使用总结
    C语言中函数的使用及多文件团队开发
    Foundation框架简介
    文件的输入与输出
  • 原文地址:https://www.cnblogs.com/huxianglin/p/6387045.html
Copyright © 2020-2023  润新知