From 9bc9b120a8cfe695c42100e74d476df5b53bdb77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=A6=E6=83=B3=E6=A9=A1=E7=9A=AE=E6=93=A6?= Date: Tue, 26 Apr 2022 11:38:17 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BD=93=E4=B9=90=E7=BD=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\345\275\225JS\345\212\240\345\257\206.js" | 607 ++++++++++++++++++ 1 file changed, 607 insertions(+) create mode 100644 "\345\212\240\345\257\206JS/\345\275\223\344\271\220\347\275\221\347\231\273\345\275\225JS\345\212\240\345\257\206.js" diff --git "a/\345\212\240\345\257\206JS/\345\275\223\344\271\220\347\275\221\347\231\273\345\275\225JS\345\212\240\345\257\206.js" "b/\345\212\240\345\257\206JS/\345\275\223\344\271\220\347\275\221\347\231\273\345\275\225JS\345\212\240\345\257\206.js" new file mode 100644 index 0000000..f42536f --- /dev/null +++ "b/\345\212\240\345\257\206JS/\345\275\223\344\271\220\347\275\221\347\231\273\345\275\225JS\345\212\240\345\257\206.js" @@ -0,0 +1,607 @@ +/* + * Copyright (c) 2015 Eric Wilde. + * Copyright 1998-2015 David Shapiro. + * + * RSA.js is a suite of routines for performing RSA public-key computations + * in JavaScript. The cryptographic functions herein are used for encoding + * and decoding strings to be sent over unsecure channels. + * + * To use these routines, a pair of public/private keys is created through a + * number of means (OpenSSL tools on Linux/Unix, Dave Shapiro's + * RSAKeyGenerator program on Windows). These keys are passed to RSAKeyPair + * as hexadecimal strings to create an encryption key object. This key object + * is then used with encryptedString to encrypt blocks of plaintext using the + * public key. The resulting cyphertext blocks can be decrypted with + * decryptedString. + * + * Note that the cryptographic functions herein are complementary to those + * found in CryptoFuncs.php and CryptoFuncs.pm. Hence, encrypted messages may + * be sent between programs written in any of those languages. The most + * useful, of course is to send messages encrypted by a Web page using RSA.js + * to a PHP or Perl script running on a Web servitron. + * + * Also, the optional padding flag may be specified on the call to + * encryptedString, in which case blocks of cyphertext that are compatible + * with real crypto libraries such as OpenSSL or Microsoft will be created. + * These blocks of cyphertext can then be sent to Web servitron that uses one + * of these crypto libraries for decryption. This allows messages encrypted + * with longer keys to be decrypted quickly on the Web server as well as + * making for more secure communications when a padding algorithm such as + * PKCS1v1.5 is used. + * + * These routines require BigInt.js and Barrett.js. + */ + +/*****************************************************************************/ + +/* + * Modifications + * ------------- + * + * 2014 Jan 11 E. Wilde Add optional padding flag to encryptedString + * for compatibility with real crypto libraries + * such as OpenSSL or Microsoft. Add PKCS1v1.5 + * padding. + * + * 2015 Jan 5 D. Shapiro Add optional encoding flag for encryptedString + * and encapsulate padding and encoding constants + * in RSAAPP object. + * + * Original Code + * ------------- + * + * Copyright 1998-2005 David Shapiro. + * + * You may use, re-use, abuse, copy, and modify this code to your liking, but + * please keep this header. + * + * Thanks! + * + * Dave Shapiro + * dave@ohdave.com + */ + +/*****************************************************************************/ + +var RSAAPP = {}; + +RSAAPP.NoPadding = "NoPadding"; +RSAAPP.PKCS1Padding = "PKCS1Padding"; +RSAAPP.RawEncoding = "RawEncoding"; +RSAAPP.NumericEncoding = "NumericEncoding" + +/*****************************************************************************/ + +function RSAKeyPair(encryptionExponent, decryptionExponent, modulus, keylen) +/* + * encryptionExponent The encryption exponent (i.e. public + * encryption key) to be used for + * encrypting messages. If you aren't + * doing any encrypting, a dummy + * exponent such as "10001" can be + * passed. + * + * decryptionExponent The decryption exponent (i.e. private + * decryption key) to be used for + * decrypting messages. If you aren't + * doing any decrypting, a dummy + * exponent such as "10001" can be + * passed. + * + * modulus The modulus to be used both for + * encrypting and decrypting messages. + * + * keylen The optional length of the key, in + * bits. If omitted, RSAKeyPair will + * attempt to derive a key length (but, + * see the notes below). + * + * returns The "new" object creator returns an + * instance of a key object that can be + * used to encrypt/decrypt messages. + * + * This routine is invoked as the first step in the encryption or decryption + * process to take the three numbers (expressed as hexadecimal strings) that + * are used for RSA asymmetric encryption/decryption and turn them into a key + * object that can be used for encrypting and decrypting. + * + * The key object is created thusly: + * + * RSAKey = new RSAKeyPair("ABC12345", 10001, "987654FE"); + * + * or: + * + * RSAKey = new RSAKeyPair("ABC12345", 10001, "987654FE", 64); + * + * Note that RSAKeyPair will try to derive the length of the key that is being + * used, from the key itself. The key length is especially useful when one of + * the padding options is used and/or when the encrypted messages created by + * the routine encryptedString are exchanged with a real crypto library such + * as OpenSSL or Microsoft, as it determines how many padding characters are + * appended. + * + * Usually, RSAKeyPair can determine the key length from the modulus of the + * key but this doesn't always work properly, depending on the actual value of + * the modulus. If you are exchanging messages with a real crypto library, + * such as OpenSSL or Microsoft, that depends on the fact that the blocks + * being passed to it are properly padded, you'll want the key length to be + * set properly. If that's the case, of if you just want to be sure, you + * should specify the key length that you used to generated the key, in bits + * when this routine is invoked. + */ +{ + /* + * Convert from hexadecimal and save the encryption/decryption exponents and + * modulus as big integers in the key object. + */ + this.e = biFromHex(encryptionExponent); + this.d = biFromHex(decryptionExponent); + this.m = biFromHex(modulus); + /* + * Using big integers, we can represent two bytes per element in the big + * integer array, so we calculate the chunk size as: + * + * chunkSize = 2 * (number of digits in modulus - 1) + * + * Since biHighIndex returns the high index, not the number of digits, the + * number 1 has already been subtracted from its answer. + * + * However, having said all this, "User Knows Best". If our caller passes us + * a key length (in bits), we'll treat it as gospel truth. + */ + if (typeof (keylen) != 'number') { + this.chunkSize = 2 * biHighIndex(this.m); + } else { + this.chunkSize = keylen / 8; + } + + this.radix = 16; + /* + * Precalculate the stuff used for Barrett modular reductions. + */ + this.barrett = new BarrettMu(this.m); +} + +/*****************************************************************************/ + +function encryptedString(key, s, pad, encoding) +/* + * key The previously-built RSA key whose + * public key component is to be used to + * encrypt the plaintext string. + * + * s The plaintext string that is to be + * encrypted, using the RSA assymmetric + * encryption method. + * + * pad The optional padding method to use + * when extending the plaintext to the + * full chunk size required by the RSA + * algorithm. To maintain compatibility + * with other crypto libraries, the + * padding method is described by a + * string. The default, if not + * specified is "OHDave". Here are the + * choices: + * + * OHDave - this is the original + * padding method employed by Dave + * Shapiro and Rob Saunders. If + * this method is chosen, the + * plaintext can be of any length. + * It will be padded to the correct + * length with zeros and then broken + * up into chunks of the correct + * length before being encrypted. + * The resultant cyphertext blocks + * will be separated by blanks. + * + * Note that the original code by + * Dave Shapiro reverses the byte + * order to little-endian, as the + * plaintext is encrypted. If + * either these JavaScript routines + * or one of the complementary + * PHP/Perl routines derived from + * this code is used for decryption, + * the byte order will be reversed + * again upon decryption so as to + * come out correctly. + * + * Also note that this padding + * method is claimed to be less + * secure than PKCS1Padding. + * + * NoPadding - this method truncates + * the plaintext to the length of + * the RSA key, if it is longer. If + * its length is shorter, it is + * padded with zeros. In either + * case, the plaintext string is + * reversed to preserve big-endian + * order before it is encrypted to + * maintain compatibility with real + * crypto libraries such as OpenSSL + * or Microsoft. When the + * cyphertext is to be decrypted + * by a crypto library, the + * library routine's RSAAPP.NoPadding + * flag, or its equivalent, should + * be used. + * + * Note that this padding method is + * claimed to be less secure than + * PKCS1Padding. + * + * PKCS1Padding - the PKCS1v1.5 + * padding method (as described in + * RFC 2313) is employed to pad the + * plaintext string. The plaintext + * string must be no longer than the + * length of the RSA key minus 11, + * since PKCS1v1.5 requires 3 bytes + * of overhead and specifies a + * minimum pad of 8 bytes. The + * plaintext string is padded with + * randomly-generated bytes and then + * its order is reversed to preserve + * big-endian order before it is + * encrypted to maintain + * compatibility with real crypto + * libraries such as OpenSSL or + * Microsoft. When the cyphertext + * is to be decrypted by a crypto + * library, the library routine's + * RSAAPP.PKCS1Padding flag, or its + * equivalent, should be used. + * + * encoding The optional encoding scheme to use + * for the return value. If ommitted, + * numeric encoding will be used. + * + * RawEncoding - The return value + * is given as its raw value. + * This is the easiest method when + * interoperating with server-side + * OpenSSL, as no additional conversion + * is required. Use the constant + * RSAAPP.RawEncoding for this option. + * + * NumericEncoding - The return value + * is given as a number in hexadecimal. + * Perhaps useful for debugging, but + * will need to be translated back to + * its raw equivalent (e.g. using + * PHP's hex2bin) before using with + * OpenSSL. Use the constant + * RSAAPP.NumericEncoding for this option. + * + * returns The cyphertext block that results + * from encrypting the plaintext string + * s with the RSA key. + * + * This routine accepts a plaintext string that is to be encrypted with the + * public key component of the previously-built RSA key using the RSA + * assymmetric encryption method. Before it is encrypted, the plaintext + * string is padded to the same length as the encryption key for proper + * encryption. + * + * Depending on the padding method chosen, an optional header with block type + * is prepended, the plaintext is padded using zeros or randomly-generated + * bytes, and then the plaintext is possibly broken up into chunks. + * + * Note that, for padding with zeros, this routine was altered by Rob Saunders + * (rob@robsaunders.net). The new routine pads the string after it has been + * converted to an array. This fixes an incompatibility with Flash MX's + * ActionScript. + * + * The various padding schemes employed by this routine, and as presented to + * RSA for encryption, are shown below. Note that the RSA encryption done + * herein reverses the byte order as encryption is done: + * + * Plaintext In + * ------------ + * + * d5 d4 d3 d2 d1 d0 + * + * OHDave + * ------ + * + * d5 d4 d3 d2 d1 d0 00 00 00 /.../ 00 00 00 00 00 00 00 00 + * + * NoPadding + * --------- + * + * 00 00 00 00 00 00 00 00 00 /.../ 00 00 d0 d1 d2 d3 d4 d5 + * + * PKCS1Padding + * ------------ + * + * d0 d1 d2 d3 d4 d5 00 p0 p1 /.../ p2 p3 p4 p5 p6 p7 02 00 + * \------------ ------------/ + * \/ + * Minimum 8 bytes pad length + */ +{ + var a = new Array(); // The usual Alice and Bob stuff + var sl = s.length; // Plaintext string length + var i, j, k; // The usual Fortran index stuff + var padtype; // Type of padding to do + var encodingtype; // Type of output encoding + var rpad; // Random pad + var al; // Array length + var result = ""; // Cypthertext result + var block; // Big integer block to encrypt + var crypt; // Big integer result + var text; // Text result + /* + * Figure out the padding type. + */ + if (typeof (pad) == 'string') { + if (pad == RSAAPP.NoPadding) { + padtype = 1; + } else if (pad == RSAAPP.PKCS1Padding) { + padtype = 2; + } else { + padtype = 0; + } + } else { + padtype = 0; + } + /* + * Determine encoding type. + */ + if (typeof (encoding) == 'string' && encoding == RSAAPP.RawEncoding) { + encodingtype = 1; + } else { + encodingtype = 0; + } + + /* + * If we're not using Dave's padding method, we need to truncate long + * plaintext blocks to the correct length for the padding method used: + * + * NoPadding - key length + * PKCS1Padding - key length - 11 + */ + if (padtype == 1) { + if (sl > key.chunkSize) { + sl = key.chunkSize; + } + } else if (padtype == 2) { + if (sl > (key.chunkSize - 11)) { + sl = key.chunkSize - 11; + } + } + /* + * Convert the plaintext string to an array of characters so that we can work + * with individual characters. + * + * Note that, if we're talking to a real crypto library at the other end, we + * reverse the plaintext order to preserve big-endian order. + */ + i = 0; + + if (padtype == 2) { + j = sl - 1; + } else { + j = key.chunkSize - 1; + } + + while (i < sl) { + if (padtype) { + a[j] = s.charCodeAt(i); + } else { + a[i] = s.charCodeAt(i); + } + + i++; + j--; + } + /* + * Now is the time to add the padding. + * + * If we're doing PKCS1v1.5 padding, we pick up padding where we left off and + * pad the remainder of the block. Otherwise, we pad at the front of the + * block. This gives us the correct padding for big-endian blocks. + * + * The padding is either a zero byte or a randomly-generated non-zero byte. + */ + if (padtype == 1) { + i = 0; + } + + j = key.chunkSize - (sl % key.chunkSize); + + while (j > 0) { + if (padtype == 2) { + rpad = Math.floor(Math.random() * 256); + + while (!rpad) { + rpad = Math.floor(Math.random() * 256); + } + + a[i] = rpad; + } else { + a[i] = 0; + } + + i++; + j--; + } + /* + * For PKCS1v1.5 padding, we need to fill in the block header. + * + * According to RFC 2313, a block type, a padding string, and the data shall + * be formatted into the encryption block: + * + * EncrBlock = 00 || BlockType || PadString || 00 || Data + * + * The block type shall be a single octet indicating the structure of the + * encryption block. For this version of the document it shall have value 00, + * 01, or 02. For a private-key operation, the block type shall be 00 or 01. + * For a public-key operation, it shall be 02. + * + * The padding string shall consist of enough octets to pad the encryption + * block to the length of the encryption key. For block type 00, the octets + * shall have value 00; for block type 01, they shall have value FF; and for + * block type 02, they shall be pseudorandomly generated and nonzero. + * + * Note that in a previous step, we wrote padding bytes into the first three + * bytes of the encryption block because it was simpler to do so. We now + * overwrite them. + */ + if (padtype == 2) { + a[sl] = 0; + a[key.chunkSize - 2] = 2; + a[key.chunkSize - 1] = 0; + } + /* + * Carve up the plaintext and encrypt each of the resultant blocks. + */ + al = a.length; + + for (i = 0; i < al; i += key.chunkSize) { + /* + * Get a block. + */ + block = new BigInt(); + + j = 0; + + for (k = i; k < (i + key.chunkSize); ++j) { + block.digits[j] = a[k++]; + block.digits[j] += a[k++] << 8; + } + /* + * Encrypt it, convert it to text, and append it to the result. + */ + crypt = key.barrett.powMod(block, key.e); + if (encodingtype == 1) { + text = biToBytes(crypt); + } else { + text = (key.radix == 16) ? biToHex(crypt) : biToString(crypt, key.radix); + } + result += text; + } + /* + * Return the result, removing the last space. + */ + //result = (result.substring(0, result.length - 1)); + return result; +} + +/*****************************************************************************/ + +function decryptedString(key, c) +/* + * key The previously-built RSA key whose + * private key component is to be used + * to decrypt the cyphertext string. + * + * c The cyphertext string that is to be + * decrypted, using the RSA assymmetric + * encryption method. + * + * returns The plaintext block that results from + * decrypting the cyphertext string c + * with the RSA key. + * + * This routine is the complementary decryption routine that is meant to be + * used for JavaScript decryption of cyphertext blocks that were encrypted + * using the OHDave padding method of the encryptedString routine (in this + * module). It can also decrypt cyphertext blocks that were encrypted by + * RSAEncode (in CryptoFuncs.pm or CryptoFuncs.php) so that encrypted + * messages can be sent of insecure links (e.g. HTTP) to a Web page. + * + * It accepts a cyphertext string that is to be decrypted with the public key + * component of the previously-built RSA key using the RSA assymmetric + * encryption method. Multiple cyphertext blocks are broken apart, if they + * are found in c, and each block is decrypted. All of the decrypted blocks + * are concatenated back together to obtain the original plaintext string. + * + * This routine assumes that the plaintext was padded to the same length as + * the encryption key with zeros. Therefore, it removes any zero bytes that + * are found at the end of the last decrypted block, before it is appended to + * the decrypted plaintext string. + * + * Note that the encryptedString routine (in this module) works fairly quickly + * simply by virtue of the fact that the public key most often chosen is quite + * short (e.g. 0x10001). This routine does not have that luxury. The + * decryption key that it must employ is the full key length. For long keys, + * this can result in serious timing delays (e.g. 7-8 seconds to decrypt using + * 2048 bit keys on a reasonably fast machine, under the Firefox Web browser). + * + * If you intend to send encrypted messagess to a JavaScript program running + * under a Web browser, you might consider using shorter keys to keep the + * decryption times low. Alternately, a better scheme is to generate a random + * key for use by a symmetric encryption algorithm and transmit it to the + * other end, after encrypting it with encryptedString. The other end can use + * a real crypto library (e.g. OpenSSL or Microsoft) to decrypt the key and + * then use it to encrypt all of the messages (with a symmetric encryption + * algorithm such as Twofish or AES) bound for the JavaScript program. + * Symmetric decryption is orders of magnitude faster than asymmetric and + * should yield low decryption times, even when executed in JavaScript. + * + * Also note that only the OHDave padding method (e.g. zeros) is supported by + * this routine *AND* that this routine expects little-endian cyphertext, as + * created by the encryptedString routine (in this module) or the RSAEncode + * routine (in either CryptoFuncs.pm or CryptoFuncs.php). You can use one of + * the real crypto libraries to create cyphertext that can be decrypted by + * this routine, if you reverse the plaintext byte order first and then + * manually pad it with zero bytes. The plaintext should then be encrypted + * with the NoPadding flag or its equivalent in the crypto library of your + * choice. + */ +{ + var blocks = c.split(" "); // Multiple blocks of cyphertext + var b; // The usual Alice and Bob stuff + var i, j; // The usual Fortran index stuff + var bi; // Cyphertext as a big integer + var result = ""; // Plaintext result + /* + * Carve up the cyphertext into blocks. + */ + for (i = 0; i < blocks.length; ++i) { + /* + * Depending on the radix being used for the key, convert this cyphertext + * block into a big integer. + */ + if (key.radix == 16) { + bi = biFromHex(blocks[i]); + } else { + bi = biFromString(blocks[i], key.radix); + } + /* + * Decrypt the cyphertext. + */ + b = key.barrett.powMod(bi, key.d); + /* + * Convert the decrypted big integer back to the plaintext string. Since + * we are using big integers, each element thereof represents two bytes of + * plaintext. + */ + for (j = 0; j <= biHighIndex(b); ++j) { + result += String.fromCharCode(b.digits[j] & 255, b.digits[j] >> 8); + } + } + /* + * Remove trailing null, if any. + */ + if (result.charCodeAt(result.length - 1) == 0) { + result = result.substring(0, result.length - 1); + } + /* + * Return the plaintext. + */ + return (result); +} + +//密码加密 +var rsa = function (arg) { + setMaxDigits(130); + var PublicExponent = "10001"; + var modulus = "be44aec4d73408f6b60e6fe9e3dc55d0e1dc53a1e171e071b547e2e8e0b7da01c56e8c9bcf0521568eb111adccef4e40124b76e33e7ad75607c227af8f8e0b759c30ef283be8ab17a84b19a051df5f94c07e6e7be5f77866376322aac944f45f3ab532bb6efc70c1efa524d821d16cafb580c5a901f0defddea3692a4e68e6cd"; + var key = new RSAKeyPair(PublicExponent, "", modulus); + return encryptedString(key, arg); +}; \ No newline at end of file -- GitLab