V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
zyqf
V2EX  ›  问与答

爬虫模拟登录中,目标网站使用 JS 加密密码再 POST,是选择模拟一遍 JS 代码,还是选择使用 JS 引擎获得运行结果?

  •  
  •   zyqf · 2018-03-01 16:59:30 +08:00 · 4449 次点击
    这是一个创建于 2450 天前的主题,其中的信息可能已经有所发展或是发生改变。

    主要部分

    各位前辈,你们是选择照着 JS 代码敲一遍具体代码,还是选择使用 js 引擎获得运行结果呢?

    如果是自己实现 JS 功能的话,我放出关键的 JS 代码,感觉工作量略大。。。。。

    两个变量

    {"exponent":"AQAB","modulus":"AKpNUUppYjjjE7HljGMT4ufwytJIEoz68S0+K3\/Wvjwotal0lUlu3xvnzlJR3OCrkxEzk4Oa5zvKUhMARip4oO+dprByj97ip7k2M70O8ft28mLs95WEkiMNiLrWJ66hE1pABLSEAxX1RObZsoo\/8XSQ+NlqkwcCY\/cC5nuoG95V"}
    

    登录加密关键代码

    var rsaKey = new RSAKey();
    		rsaKey.setPublic(b64tohex(modulus), b64tohex(exponent));
    		var enPassword = hex2b64(rsaKey.encrypt($("#mm").val()));
    		$("#mm").val(enPassword);
    		$("#hidMm").val(enPassword);
    

    rsa.js

    // Depends on jsbn.js and rng.js
    
    // Version 1.1: support utf-8 encoding in pkcs1pad2
    
    // convert a (hex) string to a bignum object
    function parseBigInt(str,r) {
      return new BigInteger(str,r);
    }
    
    function linebrk(s,n) {
      var ret = "";
      var i = 0;
      while(i + n < s.length) {
        ret += s.substring(i,i+n) + "\n";
        i += n;
      }
      return ret + s.substring(i,s.length);
    }
    
    function byte2Hex(b) {
      if(b < 0x10)
        return "0" + b.toString(16);
      else
        return b.toString(16);
    }
    
    // PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
    function pkcs1pad2(s,n) {
      if(n < s.length + 11) { // TODO: fix for utf-8
        alert("Message too long for RSA");
        return null;
      }
      var ba = new Array();
      var i = s.length - 1;
      while(i >= 0 && n > 0) {
        var c = s.charCodeAt(i--);
        if(c < 128) { // encode using utf-8
          ba[--n] = c;
        }
        else if((c > 127) && (c < 2048)) {
          ba[--n] = (c & 63) | 128;
          ba[--n] = (c >> 6) | 192;
        }
        else {
          ba[--n] = (c & 63) | 128;
          ba[--n] = ((c >> 6) & 63) | 128;
          ba[--n] = (c >> 12) | 224;
        }
      }
      ba[--n] = 0;
      var rng = new SecureRandom();
      var x = new Array();
      while(n > 2) { // random non-zero pad
        x[0] = 0;
        while(x[0] == 0) rng.nextBytes(x);
        ba[--n] = x[0];
      }
      ba[--n] = 2;
      ba[--n] = 0;
      return new BigInteger(ba);
    }
    
    // "empty" RSA key constructor
    function RSAKey() {
      this.n = null;
      this.e = 0;
      this.d = null;
      this.p = null;
      this.q = null;
      this.dmp1 = null;
      this.dmq1 = null;
      this.coeff = null;
    }
    
    // Set the public key fields N and e from hex strings
    function RSASetPublic(N,E) {
      if(N != null && E != null && N.length > 0 && E.length > 0) {
        this.n = parseBigInt(N,16);
        this.e = parseInt(E,16);
      }
      else
        alert("Invalid RSA public key");
    }
    
    // Perform raw public operation on "x": return x^e (mod n)
    function RSADoPublic(x) {
      return x.modPowInt(this.e, this.n);
    }
    
    // Return the PKCS#1 RSA encryption of "text" as an even-length hex string
    function RSAEncrypt(text) {
      var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3);
      if(m == null) return null;
      var c = this.doPublic(m);
      if(c == null) return null;
      var h = c.toString(16);
      if((h.length & 1) == 0) return h; else return "0" + h;
    }
    
    // Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string
    //function RSAEncryptB64(text) {
    //  var h = this.encrypt(text);
    //  if(h) return hex2b64(h); else return null;
    //}
    
    // protected
    RSAKey.prototype.doPublic = RSADoPublic;
    
    // public
    RSAKey.prototype.setPublic = RSASetPublic;
    RSAKey.prototype.encrypt = RSAEncrypt;
    //RSAKey.prototype.encrypt_b64 = RSAEncryptB64;
    
    

    base64.js

    var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    var b64pad="=";
    
    function hex2b64(h) {
      var i;
      var c;
      var ret = "";
      for(i = 0; i+3 <= h.length; i+=3) {
        c = parseInt(h.substring(i,i+3),16);
        ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);
      }
      if(i+1 == h.length) {
        c = parseInt(h.substring(i,i+1),16);
        ret += b64map.charAt(c << 2);
      }
      else if(i+2 == h.length) {
        c = parseInt(h.substring(i,i+2),16);
        ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
      }
      while((ret.length & 3) > 0) ret += b64pad;
      return ret;
    }
    
    // convert a base64 string to hex
    function b64tohex(s) {
      var ret = ""
      var i;
      var k = 0; // b64 state, 0-3
      var slop;
      for(i = 0; i < s.length; ++i) {
        if(s.charAt(i) == b64pad) break;
        v = b64map.indexOf(s.charAt(i));
        if(v < 0) continue;
        if(k == 0) {
          ret += int2char(v >> 2);
          slop = v & 3;
          k = 1;
        }
        else if(k == 1) {
          ret += int2char((slop << 2) | (v >> 4));
          slop = v & 0xf;
          k = 2;
        }
        else if(k == 2) {
          ret += int2char(slop);
          ret += int2char(v >> 2);
          slop = v & 3;
          k = 3;
        }
        else {
          ret += int2char((slop << 2) | (v >> 4));
          ret += int2char(v & 0xf);
          k = 0;
        }
      }
      if(k == 1)
        ret += int2char(slop << 2);
      return ret;
    }
    
    // convert a base64 string to a byte/number array
    function b64toBA(s) {
      //piggyback on b64tohex for now, optimize later
      var h = b64tohex(s);
      var i;
      var a = new Array();
      for(i = 0; 2*i < h.length; ++i) {
        a[i] = parseInt(h.substring(2*i,2*i+2),16);
      }
      return a;
    }
    
    
    12 条回复    2021-04-18 01:11:33 +08:00
    zhenjiachen
        1
    zhenjiachen  
       2018-03-01 17:09:47 +08:00
    我是调用 js 的方法的。
    golmic
        2
    golmic  
       2018-03-01 17:10:33 +08:00 via Android   ❤️ 1
    建议直接本地 node 跑出结果,然后 python 提交
    jackyzy823
        3
    jackyzy823  
       2018-03-01 17:11:11 +08:00 via Android
    rsa 加密…各种语言都有成熟的库…为啥要模拟 /调用 js
    zyqf
        4
    zyqf  
    OP
       2018-03-01 17:16:32 +08:00 via Android
    @jackyzy823 老哥,你看下 rsa,RSASetPublic 的方法,这种应该是非标准的。
    zyqf
        5
    zyqf  
    OP
       2018-03-01 17:20:14 +08:00 via Android
    @golmic 好的,学习新语言,我选择自己实现。🐶
    lc4t
        6
    lc4t  
       2018-03-01 17:44:32 +08:00
    不应该是先看一下目标用的什么加密,找一下 python 库里有没有写好的么..
    jackyzy823
        7
    jackyzy823  
       2018-03-01 17:58:11 +08:00
    jackyzy823
        8
    jackyzy823  
       2018-03-01 17:59:09 +08:00   ❤️ 1
    swirling
        9
    swirling  
       2018-03-01 18:17:42 +08:00   ❤️ 1
    zyqf
        11
    zyqf  
    OP
       2018-03-01 18:26:32 +08:00
    @jackyzy823 好的,是标准的,谢谢您的回答,另外是否感谢您给的在线工具~
    @swirling 感谢~
    TongNianShanHe
        12
    TongNianShanHe  
       2021-04-18 01:11:33 +08:00
    正方教务系统......
    这玩意儿搞了我一整天,心态炸了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5386 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 07:41 · PVG 15:41 · LAX 23:41 · JFK 02:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.