将RSA加密从Javascript转换为PHP

将RSA加密从Javascript转换为PHP,javascript,php,rsa,phpseclib,steam,Javascript,Php,Rsa,Phpseclib,Steam,我正在尝试登录一个网站(Steam),该网站使用Javascript RSA加密明文密码,以发送POST请求中的密文作为参数。我无法正确地将Javascript RSA从Javascript转换为PHP 当我尝试将使用任何PHP脚本创建的密文密码发送到网站时,我得到了一个不正确的登录,表明加密过程中的某些地方不正确 当从浏览器发送实际请求并使用Fiddler记录请求时,模数的位长度始终与密文的位长度相同。这也可以从Javascript函数pkcs1pad2中推断出来。这是我在尝试检查加密是否正确

我正在尝试登录一个网站(Steam),该网站使用Javascript RSA加密明文密码,以发送POST请求中的密文作为参数。我无法正确地将Javascript RSA从Javascript转换为PHP

当我尝试将使用任何PHP脚本创建的密文密码发送到网站时,我得到了一个不正确的登录,表明加密过程中的某些地方不正确

当从浏览器发送实际请求并使用Fiddler记录请求时,模数的位长度始终与密文的位长度相同。这也可以从Javascript函数pkcs1pad2中推断出来。这是我在尝试检查加密是否正确时寻找的标准之一

使用相同的公钥和明文并不总是产生与使用pkcs1时相同的密文,随机字节填充到明文的开头,直到长度与模数相同。因此,无法与通过浏览器获得的正确密文进行比较

Javascript的modPowInt($exponent,$module)和PHP的modPow($exponent,$module)是否执行不同的计算,因为PHP RSA(2)不起作用,尽管它似乎与Javascript RSA完全相同


Javascript RSA-需要转换为PHP的内容

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);
        if(($data.length & 1) == 1)
            $data = "0" + $data;
        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);
    }
};

PHP RSA(2) 我尝试将Javascript RSA脚本转换为PHP。比特长度与模数不一致(2472而非2048)

包括'phpseclib/Math/biginger.php';
包括“phpseclib/Crypt/RSA.php”;
函数加密($data,$mod,$exp){
$mod=新的数学大整数($mod,16);
$exp=新的数学大整数($exp,16);
如果($exp==null | |$mod==null)返回false;
$data=pkcs1pad2($data,(strlen($mod->toBits())+7)>>3);
如果($data==null),则返回false;
$data=$data->modPow($exp,$mod);
如果($data==null),则返回false;
$data=$data->toString();
if((strlen($data)&1)==1)
$data=“0”。$data;
返回urlencode(base64_编码(hex2bin($data));
}
函数pkcs1pad2($data,$keysize){
如果($keysize=0&&$keysize>0)
$buffer[--$keysize]=$data[$i--];
$buffer[--$keysize]=0;
而($keysize>2)
$buffer[--$keysize]=rand(0255);
$buffer[--$keysize]=2;
$buffer[--$keysize]=0;
返回新的Math_BigInteger(bin2hex(内爆(“”,$buffer)),16);
}

PHP RSA(3) 这是我代码的最后一次迭代。我尝试填充缺失的位,使位长度与模(2048)的长度相同,但成功了。但网站仍然认为密文密码不正确

include('Crypt/RSA.php');
include('Math/BigInteger.php');

function hex_to_binary($hex) {
    $binary = '';
    for ($i = 0; $i < strlen($hex); $i += 2) {
        $hexChunk = substr($hex, $i, 2);
        $intChunk = hexdec($hexChunk);
        $binaryChunk = decbin($intChunk);
        $binaryChunk = str_pad($binaryChunk, 8, '0', STR_PAD_LEFT);
        $binary .= $binaryChunk;
    }
    return $binary;
}

function bytes_to_binary($bytes) {
    $binary = '';
    foreach($bytes as $integer) {
        $byte = decbin($integer);
        $byte = str_pad($byte, 8, '0', STR_PAD_LEFT);
        $binary .= $byte;
    }
    return $binary;
}

function binary_to_text($binary) {
    $text = '';
    $binaryLength = strlen($binary);
    for ($i = 0; $i < $binaryLength; $i += 8) {
        $binaryChunk = substr($binary, $i, 8);
        $characterCode = bindec($binaryChunk);
        $character = chr($characterCode);
        $text .= $character;
    }
    return $text;
}

function getPublicKey($modulusHex, $exponentHex) {
    $publicKey = Array(
        'modulus' => $modulusHex,
        'exponent' => $exponentHex
    );
    return $publicKey;
}

function pkcs1pad2($data, $publicKey) {
    // Convert Modulus from Hex to Binary
    $modulusBinary = hex_to_binary($publicKey['modulus']);
    // Get Bytes of Modulus
    $modulusInteger = new Math_BigInteger($modulusBinary, 2);
    $modulusBytes = ceil(strlen($modulusInteger->toBits()) / 8);
    // Bytes in the Modulus must be 11 Bytes longer than Bytes in the Password (UTF-8 => 8 Bytes per Character)
    if($modulusBytes < strlen($data) + 11) {
        // Otherwise Encryption is impossible so Return Null
        return null;
    };
    // Array to Store Sequence of Bytes in the Padded Password
    $buffer = array();
    // Variables to Hold Current Position of Bytes and Characters
    $currentModulusByte = $modulusBytes;
    $currentDataCharacter = strlen($data) - 1;
    // Insert Password into End of Buffer
    while($currentDataCharacter >= 0 && $currentModulusByte > 0) {
        $buffer[--$currentModulusByte] = ord($data[$currentModulusByte--]);
    };
    // Insert 0 as the Next Last Value of Buffer
    $Buffer[--$currentModulusByte] = 0;
    // Insert Random Bytes into Buffer until the First 2 Bytes
    while($currentModulusByte > 2) {
        $buffer[--$currentModulusByte] = rand(1,255);
    };
    // Insert 0 and 2 as the First 2 Bytes in the Sequence
    $buffer[--$currentModulusByte] = 2;
    $buffer[--$currentModulusByte] = 0;
    // Math_BigInteger() doesn't accept an Array of Bytes so convert it to a Binary string
    $paddedModulusBinary = bytes_to_binary($buffer);
    // Convert Binary to BigInteger using a Base 2
    $paddedModulusInteger = new Math_BigInteger($paddedModulusBinary, 2);
    return $paddedModulusInteger;
}

// Copy of the Encrypt function
function encrypt($data, $publicKey) {
    // Make Sure that the Public Key is not Null
    if(!$publicKey) {
        return false;
    };
    // Pad the Data for Encryption
    $paddedData = pkcs1pad2($data, $publicKey);
    // Make Sure that the Padded Data is not Null
    if(!$paddedData) {
        return false;
    };
    // Encrypt the Padded Data using the Public Key
    $exponentBinary = hex_to_binary($publicKey['exponent']);
    $exponentBigInt = new Math_BigInteger($exponentBinary, 2);
    $modulusBinary = hex_to_binary($publicKey['modulus']);
    $modulusBigInt = new Math_BigInteger($modulusBinary, 2);
    $encryptedData = $paddedData->modPow($exponentBigInt, $modulusBigInt);
    // Make Sure that the Encrypted Data is not Null
    if(!$encryptedData) {
        return false;
    }
    // Convert the Encrypted Data to Binary
    $encryptedBinaryData = $encryptedData->toBits();
    // Pad Empty Bits onto the Start of the Encrypted Binary Data
    $modulusBitLength = strlen($publicKey['modulus']) * 4;
    $encryptedBinaryData = str_pad($encryptedBinaryData, $modulusBitLength, '0', STR_PAD_LEFT);
    // Convert Binary to Text
    $textData = binary_to_text($encryptedBinaryData);
    // Encode Binary with Base64
    $base64EncodedData = base64_encode($textData);
    // Encode Base64 for Url
    $urlEncodedData = urlencode($base64EncodedData);
    return $urlEncodedData;
 }
include('Crypt/RSA.php');
包括('Math/biginger.php');
函数十六进制到二进制($hex){
$binary='';
对于($i=0;$i$ModuleUshex,
“指数”=>$exponentHex
);
返回$publicKey;
}
函数pkcs1pad2($data,$publicKey){
//将模数从十六进制转换为二进制
$moduleusbinary=十六进制到二进制($publicKey['modules']);
//获取模数的字节数
$modulusInteger=新的数学\u BigInteger($modulusBinary,2);
$moduleusbytes=ceil(strlen($moduleusinteger->toBits())/8);
//模数中的字节必须比密码中的字节长11个字节(UTF-8=>每个字符8个字节)
如果($modulesBytes=0&&$CurrentModulesByte>0){
$buffer[--$CurrentModulesByte]=ord($data[$CurrentModulesByte--]);
};
//插入0作为缓冲区的下一个最后值
$Buffer[--$CurrentModulesByte]=0;
//将随机字节插入缓冲区,直到前2个字节
而($CurrentModulesByte>2){
$buffer[--$CurrentModulesByte]=rand(1255);
};
//插入0和2作为序列中的前2个字节
$buffer[--$CurrentModulesByte]=2;
$buffer[--$CurrentModulesByte]=0;
//Math_BigInteger()不接受字节数组,因此请将其转换为二进制字符串
$paddedModulusBinary=字节到二进制($buffer);
//使用基数2将二进制转换为BigInteger
$paddedModulusInteger=新的数学大整数($paddedModulusInary,2);
返回$paddedModulusInteger;
}
//加密函数的副本
函数加密($data,$publicKey){
//确保公钥不为Null
如果(!$publicKey){
返回false;
};
//将数据填充到
include 'phpseclib/Math/BigInteger.php';
include 'phpseclib/Crypt/RSA.php';

function encrypt($data, $mod, $exp){
    $mod = new Math_BigInteger($mod,16);
    $exp = new Math_BigInteger($exp,16);
    if($exp == null || $mod == null) return false;
    $data = pkcs1pad2($data, (strlen($mod->toBits())+7)>>3);
    if($data == null) return false;
    $data = $data->modPow($exp,$mod);
    if($data == null) return false;
    $data = $data->toString();
    if((strlen($data) & 1) == 1)
        $data = "0" . $data;
    return urlencode(base64_encode(hex2bin($data)));
}

function pkcs1pad2($data, $keysize){
    if($keysize < strlen($data) + 11)
        return null;
    $buffer = array();
    $i = strlen($data)-1;
    while($i >= 0 && $keysize > 0)
        $buffer[--$keysize] = $data[$i--];
    $buffer[--$keysize] = 0;
    while($keysize > 2)
        $buffer[--$keysize] = rand(0,255);
    $buffer[--$keysize] = 2;
    $buffer[--$keysize] = 0;
    return new Math_BigInteger(bin2hex(implode('',$buffer)), 16);
}
include('Crypt/RSA.php');
include('Math/BigInteger.php');

function hex_to_binary($hex) {
    $binary = '';
    for ($i = 0; $i < strlen($hex); $i += 2) {
        $hexChunk = substr($hex, $i, 2);
        $intChunk = hexdec($hexChunk);
        $binaryChunk = decbin($intChunk);
        $binaryChunk = str_pad($binaryChunk, 8, '0', STR_PAD_LEFT);
        $binary .= $binaryChunk;
    }
    return $binary;
}

function bytes_to_binary($bytes) {
    $binary = '';
    foreach($bytes as $integer) {
        $byte = decbin($integer);
        $byte = str_pad($byte, 8, '0', STR_PAD_LEFT);
        $binary .= $byte;
    }
    return $binary;
}

function binary_to_text($binary) {
    $text = '';
    $binaryLength = strlen($binary);
    for ($i = 0; $i < $binaryLength; $i += 8) {
        $binaryChunk = substr($binary, $i, 8);
        $characterCode = bindec($binaryChunk);
        $character = chr($characterCode);
        $text .= $character;
    }
    return $text;
}

function getPublicKey($modulusHex, $exponentHex) {
    $publicKey = Array(
        'modulus' => $modulusHex,
        'exponent' => $exponentHex
    );
    return $publicKey;
}

function pkcs1pad2($data, $publicKey) {
    // Convert Modulus from Hex to Binary
    $modulusBinary = hex_to_binary($publicKey['modulus']);
    // Get Bytes of Modulus
    $modulusInteger = new Math_BigInteger($modulusBinary, 2);
    $modulusBytes = ceil(strlen($modulusInteger->toBits()) / 8);
    // Bytes in the Modulus must be 11 Bytes longer than Bytes in the Password (UTF-8 => 8 Bytes per Character)
    if($modulusBytes < strlen($data) + 11) {
        // Otherwise Encryption is impossible so Return Null
        return null;
    };
    // Array to Store Sequence of Bytes in the Padded Password
    $buffer = array();
    // Variables to Hold Current Position of Bytes and Characters
    $currentModulusByte = $modulusBytes;
    $currentDataCharacter = strlen($data) - 1;
    // Insert Password into End of Buffer
    while($currentDataCharacter >= 0 && $currentModulusByte > 0) {
        $buffer[--$currentModulusByte] = ord($data[$currentModulusByte--]);
    };
    // Insert 0 as the Next Last Value of Buffer
    $Buffer[--$currentModulusByte] = 0;
    // Insert Random Bytes into Buffer until the First 2 Bytes
    while($currentModulusByte > 2) {
        $buffer[--$currentModulusByte] = rand(1,255);
    };
    // Insert 0 and 2 as the First 2 Bytes in the Sequence
    $buffer[--$currentModulusByte] = 2;
    $buffer[--$currentModulusByte] = 0;
    // Math_BigInteger() doesn't accept an Array of Bytes so convert it to a Binary string
    $paddedModulusBinary = bytes_to_binary($buffer);
    // Convert Binary to BigInteger using a Base 2
    $paddedModulusInteger = new Math_BigInteger($paddedModulusBinary, 2);
    return $paddedModulusInteger;
}

// Copy of the Encrypt function
function encrypt($data, $publicKey) {
    // Make Sure that the Public Key is not Null
    if(!$publicKey) {
        return false;
    };
    // Pad the Data for Encryption
    $paddedData = pkcs1pad2($data, $publicKey);
    // Make Sure that the Padded Data is not Null
    if(!$paddedData) {
        return false;
    };
    // Encrypt the Padded Data using the Public Key
    $exponentBinary = hex_to_binary($publicKey['exponent']);
    $exponentBigInt = new Math_BigInteger($exponentBinary, 2);
    $modulusBinary = hex_to_binary($publicKey['modulus']);
    $modulusBigInt = new Math_BigInteger($modulusBinary, 2);
    $encryptedData = $paddedData->modPow($exponentBigInt, $modulusBigInt);
    // Make Sure that the Encrypted Data is not Null
    if(!$encryptedData) {
        return false;
    }
    // Convert the Encrypted Data to Binary
    $encryptedBinaryData = $encryptedData->toBits();
    // Pad Empty Bits onto the Start of the Encrypted Binary Data
    $modulusBitLength = strlen($publicKey['modulus']) * 4;
    $encryptedBinaryData = str_pad($encryptedBinaryData, $modulusBitLength, '0', STR_PAD_LEFT);
    // Convert Binary to Text
    $textData = binary_to_text($encryptedBinaryData);
    // Encode Binary with Base64
    $base64EncodedData = base64_encode($textData);
    // Encode Base64 for Url
    $urlEncodedData = urlencode($base64EncodedData);
    return $urlEncodedData;
 }