使用RSA(Java)加密密码

时间:2014-05-30 20:30:12

标签: java javascript encryption rsa biginteger

我正在使用RSA加密我的Steam密码,然后登录到我的Steam帐户,但尝试后我总是收到{success:false}消息,这是Steam用于登录系统的javascript代码:

var RSAPublicKey = function($modulus_hex, $encryptionExponent_hex) {
this.modulus = new BigInteger( $modulus_hex, 16);
this.encryptionExponent = new BigInteger( $encryptionExponent_hex, 16);
}

var Base64 = {
base64: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
encode: function($input) {
    if (!$input) {
        return false;
    }
    var $output = "";
    var $chr1, $chr2, $chr3;
    var $enc1, $enc2, $enc3, $enc4;
    var $i = 0;
    do {
        $chr1 = $input.charCodeAt($i++);
        $chr2 = $input.charCodeAt($i++);
        $chr3 = $input.charCodeAt($i++);
        $enc1 = $chr1 >> 2;
        $enc2 = (($chr1 & 3) << 4) | ($chr2 >> 4);
        $enc3 = (($chr2 & 15) << 2) | ($chr3 >> 6);
        $enc4 = $chr3 & 63;
        if (isNaN($chr2)) $enc3 = $enc4 = 64;
        else if (isNaN($chr3)) $enc4 = 64;
        $output += this.base64.charAt($enc1) + this.base64.charAt($enc2) + this.base64.charAt($enc3) + this.base64.charAt($enc4);
    } while ($i < $input.length);
    return $output;
},
decode: function($input) {
    if(!$input) return false;
    $input = $input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
    var $output = "";
    var $enc1, $enc2, $enc3, $enc4;
    var $i = 0;
    do {
        $enc1 = this.base64.indexOf($input.charAt($i++));
        $enc2 = this.base64.indexOf($input.charAt($i++));
        $enc3 = this.base64.indexOf($input.charAt($i++));
        $enc4 = this.base64.indexOf($input.charAt($i++));
        $output += String.fromCharCode(($enc1 << 2) | ($enc2 >> 4));
        if ($enc3 != 64) $output += String.fromCharCode((($enc2 & 15) << 4) | ($enc3 >> 2));
        if ($enc4 != 64) $output += String.fromCharCode((($enc3 & 3) << 6) | $enc4);
    } while ($i < $input.length);
    return $output; 
}
};

var Hex = {
hex: "0123456789abcdef",
encode: function($input) {
    if(!$input) return false;
    var $output = "";
    var $k;
    var $i = 0;
    do {
        $k = $input.charCodeAt($i++);
        $output += this.hex.charAt(($k >> 4) &0xf) + this.hex.charAt($k & 0xf);
    } while ($i < $input.length);
    return $output;
},
decode: function($input) {
    if(!$input) return false;
    $input = $input.replace(/[^0-9abcdef]/g, "");
    var $output = "";
    var $i = 0;
    do {
        $output += String.fromCharCode(((this.hex.indexOf($input.charAt($i++)) << 4) & 0xf0) | (this.hex.indexOf($input.charAt($i++)) & 0xf));
    } while ($i < $input.length);
    return $output;
}
};

var RSA = {

getPublicKey: function( $modulus_hex, $exponent_hex ) {
    return new RSAPublicKey( $modulus_hex, $exponent_hex );
},

encrypt: function($data, $pubkey) {
    if (!$pubkey) return false;
    $data = this.pkcs1pad2($data,($pubkey.modulus.bitLength()+7)>>3);
    if(!$data) return false;
    $data = $data.modPowInt($pubkey.encryptionExponent, $pubkey.modulus);
    if(!$data) return false;
    $data = $data.toString(16);
    return Base64.encode(Hex.decode($data));
},

pkcs1pad2: function($data, $keysize) {
    if($keysize < $data.length + 11)
        return null;
    var $buffer = [];
    var $i = $data.length - 1;
    while($i >= 0 && $keysize > 0)
        $buffer[--$keysize] = $data.charCodeAt($i--);
    $buffer[--$keysize] = 0;
    while($keysize > 2)
        $buffer[--$keysize] = Math.floor(Math.random()*254) + 1;
    $buffer[--$keysize] = 2;
    $buffer[--$keysize] = 0;
    return new BigInteger($buffer);
}
}

我试图用Java重写,但我失败了:

import java.math.*;

public class RSA {

private int length2;
private BigInteger modulus;
private BigInteger exponent;

public RSA(BigInteger modulus, BigInteger exponent){
  this.modulus = modulus;
  this.exponent = exponent;
  this.length2 = (modulus.bitLength()+7)>>3;
}

public byte[] pkcs1pad2(byte[] data){
  int n = this.length2;
  byte[] bytes = new byte[n];
  int i = data.length - 1;
  while (i >= 0 && n > 11)
  {
     bytes[--n] = data[i--];
  }
  bytes[--n] = 0;

  while (n > 2)
  {
     bytes[--n] = 0x01;
  }

  bytes[--n] = 0x2;
  bytes[--n] = 0;

  return bytes;
}
public String encrypt(String text){
  if (text.length() > this.length2)
  {
     System.out.println("RSA Encrypt: Message is too big!");
  }

  BigInteger m = new BigInteger(this.pkcs1pad2(text.getBytes()));
  if (m.intValue() == 0)
  {
     return null;
  }

  BigInteger c = m.modPow(exponent, modulus);
  if (c.intValue() == 0)
  {
     return null;
  }

  String result = c.toString(16);
  if ((result.length() & 1) == 0)
  {
     return result;
  }

  return "0" + result;
}
}

我将模数和指数提供为new BigInteger(string,16) 然后我使用apache库进行Hex解码和Base64编码。

问题出在哪里?我在RSA方面并不是很有经验。

我使用的第二个代码但是也没有用:

import java.math.BigInteger;

import java.security.KeyFactory;
import java.security.Security;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPublicKeySpec;

import javax.crypto.Cipher;

public class RSA {

private BigInteger modulus;
private BigInteger exponent;
private Cipher cipher;
private RSAPublicKeySpec pubkeyspec;
private KeyFactory factory;
private RSAPublicKey pubkey;

public RSA(BigInteger modulus, BigInteger exponent) throws Exception {
    this.modulus = modulus;
    this.exponent = exponent;
    this.init();
}

private void init() throws Exception {
    this.factory = KeyFactory.getInstance("RSA");
    this.pubkeyspec = new RSAPublicKeySpec(this.modulus, this.exponent);
    this.pubkey = (RSAPublicKey) factory.generatePublic( this.pubkeyspec );

    this.cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
    this.cipher.init(Cipher.ENCRYPT_MODE, this.pubkey );

}

public byte[] encrypt(byte[] data) throws Exception {
    return this.cipher.doFinal(data);
}

public String encrypt(String data) throws Exception {
    return new String(this.encrypt(data.getBytes()));
}
}

1 个答案:

答案 0 :(得分:0)

您应该能够使用Cipher.getInstance("RSA/ECB/PKCS1Padding")而不是自己填充。这应该会大大简化您的开发。