summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRadomir Dopieralski <openstack@sheep.art.pl>2014-05-20 15:18:24 +0200
committerRadomir Dopieralski <openstack@sheep.art.pl>2014-05-20 15:18:24 +0200
commita8e4b9981fa26bf8af2ebb8f9cf5d12de8ae97db (patch)
tree73d01ffd828fdc0abeb42a97d9ca8b7b335c2432
downloadxstatic-jsencrypt-a8e4b9981fa26bf8af2ebb8f9cf5d12de8ae97db.tar.gz
Version 2.0.0 of JSEncrypt library packaged for XStatic2.0.0.1
-rw-r--r--.gitignore9
-rw-r--r--MANIFEST.in8
-rw-r--r--README.txt13
-rw-r--r--setup.py27
-rw-r--r--xstatic/__init__.py1
-rw-r--r--xstatic/pkg/__init__.py1
-rw-r--r--xstatic/pkg/jsencrypt/__init__.py49
-rw-r--r--xstatic/pkg/jsencrypt/data/jsencrypt.js478
8 files changed, 586 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b3085b8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+*.pyc
+*.sw?
+*.sqlite3
+.DS_STORE
+*.egg-info
+.venv
+.tox
+build
+dist
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..98da6f1
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,8 @@
+include README.txt
+recursive-include xstatic/pkg/jsencrypt *
+
+global-exclude *.pyc
+global-exclude *.pyo
+global-exclude *.orig
+global-exclude *.rej
+
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..c8739d5
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,13 @@
+XStatic-JSEncrypt
+--------------
+
+JSEncrypt JavaScript library packaged for setuptools (easy_install) / pip.
+
+This package is intended to be used by **any** project that needs these files.
+
+It intentionally does **not** provide any extra code except some metadata
+**nor** has any extra requirements. You MAY use some minimal support code from
+the XStatic base package, if you like.
+
+You can find more info about the xstatic packaging way in the package `XStatic`.
+
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..797b1ee
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,27 @@
+from xstatic.pkg import jsencrypt as xs
+
+# The README.txt file should be written in reST so that PyPI can use
+# it to generate your project's PyPI page.
+long_description = open('README.txt').read()
+
+from setuptools import setup, find_packages
+
+setup(
+ name=xs.PACKAGE_NAME,
+ version=xs.PACKAGE_VERSION,
+ description=xs.DESCRIPTION,
+ long_description=long_description,
+ classifiers=xs.CLASSIFIERS,
+ keywords=xs.KEYWORDS,
+ maintainer=xs.MAINTAINER,
+ maintainer_email=xs.MAINTAINER_EMAIL,
+ license=xs.LICENSE,
+ url=xs.HOMEPAGE,
+ platforms=xs.PLATFORMS,
+ packages=find_packages(),
+ namespace_packages=['xstatic', 'xstatic.pkg', ],
+ include_package_data=True,
+ zip_safe=False,
+ install_requires=[], # nothing! :)
+ # if you like, you MAY use the 'XStatic' package.
+)
diff --git a/xstatic/__init__.py b/xstatic/__init__.py
new file mode 100644
index 0000000..de40ea7
--- /dev/null
+++ b/xstatic/__init__.py
@@ -0,0 +1 @@
+__import__('pkg_resources').declare_namespace(__name__)
diff --git a/xstatic/pkg/__init__.py b/xstatic/pkg/__init__.py
new file mode 100644
index 0000000..de40ea7
--- /dev/null
+++ b/xstatic/pkg/__init__.py
@@ -0,0 +1 @@
+__import__('pkg_resources').declare_namespace(__name__)
diff --git a/xstatic/pkg/jsencrypt/__init__.py b/xstatic/pkg/jsencrypt/__init__.py
new file mode 100644
index 0000000..3a51eea
--- /dev/null
+++ b/xstatic/pkg/jsencrypt/__init__.py
@@ -0,0 +1,49 @@
+"""
+XStatic resource package
+
+See package 'XStatic' for documentation and basic tools.
+"""
+
+DISPLAY_NAME = 'JSEncrypt' # official name, upper/lowercase allowed, no spaces
+PACKAGE_NAME = 'XStatic-%s' % DISPLAY_NAME # name used for PyPi
+
+NAME = __name__.split('.')[-1] # package name (e.g. 'foo' or 'foo_bar')
+ # please use a all-lowercase valid python
+ # package name
+
+VERSION = '2.0.0' # version of the packaged files, please use the upstream
+ # version number
+BUILD = '1' # our package build number, so we can release new builds
+ # with fixes for xstatic stuff.
+PACKAGE_VERSION = VERSION + '.' + BUILD # version used for PyPi
+
+DESCRIPTION = "%s %s (XStatic packaging standard)" % (DISPLAY_NAME, VERSION)
+
+PLATFORMS = 'any'
+CLASSIFIERS = []
+KEYWORDS = '%s xstatic' % NAME
+
+# XStatic-* package maintainer:
+MAINTAINER = 'Radomir Dopieralski'
+MAINTAINER_EMAIL = 'openstack@sheep.art.pl'
+
+# this refers to the project homepage of the stuff we packaged:
+HOMEPAGE = 'http://travistidwell.com/jsencrypt/'
+
+# this refers to all files:
+LICENSE = '(same as %s)' % DISPLAY_NAME
+
+from os.path import join, dirname
+BASE_DIR = join(dirname(__file__), 'data')
+# linux package maintainers just can point to their file locations like this:
+#BASE_DIR = '/usr/share/javascript/jsencrypt'
+
+LOCATIONS = {
+ # CDN locations (if no public CDN exists, use an empty dict)
+ # if value is a string, it is a base location, just append relative
+ # path/filename. if value is a dict, do another lookup using the
+ # relative path/filename you want.
+ # your relative path/filenames should usually be without version
+ # information, because either the base dir/url is exactly for this
+ # version or the mapping will care for accessing this version.
+}
diff --git a/xstatic/pkg/jsencrypt/data/jsencrypt.js b/xstatic/pkg/jsencrypt/data/jsencrypt.js
new file mode 100644
index 0000000..a98f59c
--- /dev/null
+++ b/xstatic/pkg/jsencrypt/data/jsencrypt.js
@@ -0,0 +1,478 @@
+/**
+ * Retrieve the hexadecimal value (as a string) of the current ASN.1 element
+ * @returns {string}
+ * @public
+ */
+ASN1.prototype.getHexStringValue = function(){
+ var hexString = this.toHexString();
+ var offset = this.header * 2;
+ var length = this.length * 2;
+ return hexString.substr(offset,length);
+};
+
+/**
+ * Method to parse a pem encoded string containing both a public or private key.
+ * The method will translate the pem encoded string in a der encoded string and
+ * will parse private key and public key parameters. This method accepts public key
+ * in the rsaencryption pkcs #1 format (oid: 1.2.840.113549.1.1.1).
+ * @todo Check how many rsa formats use the same format of pkcs #1. The format is defined as:
+ * PublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * PublicKey BIT STRING
+ * }
+ * Where AlgorithmIdentifier is:
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER, the OID of the enc algorithm
+ * parameters ANY DEFINED BY algorithm OPTIONAL (NULL for PKCS #1)
+ * }
+ * and PublicKey is a SEQUENCE encapsulated in a BIT STRING
+ * RSAPublicKey ::= SEQUENCE {
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER -- e
+ * }
+ * it's possible to examine the structure of the keys obtained from openssl using
+ * an asn.1 dumper as the one used here to parse the components: http://lapo.it/asn1js/
+ * @argument {string} pem the pem encoded string, can include the BEGIN/END header/footer
+ * @private
+ */
+RSAKey.prototype.parseKey = function(pem) {
+ try{
+ var reHex = /^\s*(?:[0-9A-Fa-f][0-9A-Fa-f]\s*)+$/;
+ var der = reHex.test(pem) ? Hex.decode(pem) : Base64.unarmor(pem);
+ var asn1 = ASN1.decode(der);
+ if (asn1.sub.length === 9){
+ // the data is a Private key
+ //in order
+ //Algorithm version, n, e, d, p, q, dmp1, dmq1, coeff
+ //Alg version, modulus, public exponent, private exponent, prime 1, prime 2, exponent 1, exponent 2, coefficient
+ var modulus = asn1.sub[1].getHexStringValue(); //bigint
+ this.n = parseBigInt(modulus, 16);
+
+ var public_exponent = asn1.sub[2].getHexStringValue(); //int
+ this.e = parseInt(public_exponent, 16);
+
+ var private_exponent = asn1.sub[3].getHexStringValue(); //bigint
+ this.d = parseBigInt(private_exponent, 16);
+
+ var prime1 = asn1.sub[4].getHexStringValue(); //bigint
+ this.p = parseBigInt(prime1, 16);
+
+ var prime2 = asn1.sub[5].getHexStringValue(); //bigint
+ this.q = parseBigInt(prime2, 16);
+
+ var exponent1 = asn1.sub[6].getHexStringValue(); //bigint
+ this.dmp1 = parseBigInt(exponent1, 16);
+
+ var exponent2 = asn1.sub[7].getHexStringValue(); //bigint
+ this.dmq1 = parseBigInt(exponent2, 16);
+
+ var coefficient = asn1.sub[8].getHexStringValue(); //bigint
+ this.coeff = parseBigInt(coefficient, 16);
+
+ }else if (asn1.sub.length === 2){
+ //Public key
+ //The data PROBABLY is a public key
+ var bit_string = asn1.sub[1];
+ var sequence = bit_string.sub[0];
+
+ var modulus = sequence.sub[0].getHexStringValue();
+ this.n = parseBigInt(modulus, 16);
+ var public_exponent = sequence.sub[1].getHexStringValue();
+ this.e = parseInt(public_exponent, 16);
+
+ }else{
+ return false;
+ }
+ return true;
+ }catch(ex){
+ return false;
+ }
+};
+
+/**
+ * Translate rsa parameters in a hex encoded string representing the rsa key.
+ * The translation follow the ASN.1 notation :
+ * RSAPrivateKey ::= SEQUENCE {
+ * version Version,
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER, -- e
+ * privateExponent INTEGER, -- d
+ * prime1 INTEGER, -- p
+ * prime2 INTEGER, -- q
+ * exponent1 INTEGER, -- d mod (p1)
+ * exponent2 INTEGER, -- d mod (q-1)
+ * coefficient INTEGER, -- (inverse of q) mod p
+ * }
+ * @returns {string} DER Encoded String representing the rsa private key
+ * @private
+ */
+RSAKey.prototype.getPrivateBaseKey = function() {
+ //Algorithm version, n, e, d, p, q, dmp1, dmq1, coeff
+ //Alg version, modulus, public exponent, private exponent, prime 1, prime 2, exponent 1, exponent 2, coefficient
+ var options = {
+ 'array' : [
+ new KJUR.asn1.DERInteger({'int' : 0}),
+ new KJUR.asn1.DERInteger({'bigint' : this.n}),
+ new KJUR.asn1.DERInteger({'int' : this.e}),
+ new KJUR.asn1.DERInteger({'bigint' : this.d}),
+ new KJUR.asn1.DERInteger({'bigint' : this.p}),
+ new KJUR.asn1.DERInteger({'bigint' : this.q}),
+ new KJUR.asn1.DERInteger({'bigint' : this.dmp1}),
+ new KJUR.asn1.DERInteger({'bigint' : this.dmq1}),
+ new KJUR.asn1.DERInteger({'bigint' : this.coeff})
+ ]
+ };
+ var seq = new KJUR.asn1.DERSequence(options);
+ return seq.getEncodedHex();
+};
+
+/**
+ * base64 (pem) encoded version of the DER encoded representation
+ * @returns {string} pem encoded representation without header and footer
+ * @public
+ */
+RSAKey.prototype.getPrivateBaseKeyB64 = function (){
+ return hex2b64(this.getPrivateBaseKey());
+};
+
+/**
+ * Translate rsa parameters in a hex encoded string representing the rsa public key.
+ * The representation follow the ASN.1 notation :
+ * PublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * PublicKey BIT STRING
+ * }
+ * Where AlgorithmIdentifier is:
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER, the OID of the enc algorithm
+ * parameters ANY DEFINED BY algorithm OPTIONAL (NULL for PKCS #1)
+ * }
+ * and PublicKey is a SEQUENCE encapsulated in a BIT STRING
+ * RSAPublicKey ::= SEQUENCE {
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER -- e
+ * }
+ * @returns {string} DER Encoded String representing the rsa public key
+ * @private
+ */
+RSAKey.prototype.getPublicBaseKey = function() {
+ var options = {
+ 'array' : [
+ new KJUR.asn1.DERObjectIdentifier({'oid':'1.2.840.113549.1.1.1'}), //RSA Encryption pkcs #1 oid
+ new KJUR.asn1.DERNull()
+ ]
+ };
+ var first_sequence = new KJUR.asn1.DERSequence(options);
+
+ options = {
+ 'array' : [
+ new KJUR.asn1.DERInteger({'bigint' : this.n}),
+ new KJUR.asn1.DERInteger({'int' : this.e})
+ ]
+ };
+ var second_sequence = new KJUR.asn1.DERSequence(options);
+
+ options = {
+ 'hex' : '00'+second_sequence.getEncodedHex()
+ };
+ var bit_string = new KJUR.asn1.DERBitString(options);
+
+ options = {
+ 'array' : [
+ first_sequence,
+ bit_string
+ ]
+ };
+ var seq = new KJUR.asn1.DERSequence(options);
+ return seq.getEncodedHex();
+};
+
+/**
+ * base64 (pem) encoded version of the DER encoded representation
+ * @returns {string} pem encoded representation without header and footer
+ * @public
+ */
+RSAKey.prototype.getPublicBaseKeyB64 = function (){
+ return hex2b64(this.getPublicBaseKey());
+};
+
+/**
+ * wrap the string in block of width chars. The default value for rsa keys is 64
+ * characters.
+ * @param {string} str the pem encoded string without header and footer
+ * @param {Number} [width=64] - the length the string has to be wrapped at
+ * @returns {string}
+ * @private
+ */
+RSAKey.prototype.wordwrap = function(str, width) {
+ width = width || 64;
+ if (!str)
+ return str;
+ var regex = '(.{1,' + width + '})( +|$\n?)|(.{1,' + width + '})';
+ return str.match(RegExp(regex, 'g')).join('\n');
+};
+
+/**
+ * Retrieve the pem encoded private key
+ * @returns {string} the pem encoded private key with header/footer
+ * @public
+ */
+RSAKey.prototype.getPrivateKey = function() {
+ var key = "-----BEGIN RSA PRIVATE KEY-----\n";
+ key += this.wordwrap(this.getPrivateBaseKeyB64()) + "\n";
+ key += "-----END RSA PRIVATE KEY-----";
+ return key;
+};
+
+/**
+ * Retrieve the pem encoded public key
+ * @returns {string} the pem encoded public key with header/footer
+ * @public
+ */
+RSAKey.prototype.getPublicKey = function() {
+ var key = "-----BEGIN PUBLIC KEY-----\n";
+ key += this.wordwrap(this.getPublicBaseKeyB64()) + "\n";
+ key += "-----END PUBLIC KEY-----";
+ return key;
+};
+
+/**
+ * Check if the object contains the necessary parameters to populate the rsa modulus
+ * and public exponent parameters.
+ * @param {Object} [obj={}] - An object that may contain the two public key
+ * parameters
+ * @returns {boolean} true if the object contains both the modulus and the public exponent
+ * properties (n and e)
+ * @todo check for types of n and e. N should be a parseable bigInt object, E should
+ * be a parseable integer number
+ * @private
+ */
+RSAKey.prototype.hasPublicKeyProperty = function(obj){
+ obj = obj || {};
+ return obj.hasOwnProperty('n') &&
+ obj.hasOwnProperty('e');
+};
+
+/**
+ * Check if the object contains ALL the parameters of an RSA key.
+ * @param {Object} [obj={}] - An object that may contain nine rsa key
+ * parameters
+ * @returns {boolean} true if the object contains all the parameters needed
+ * @todo check for types of the parameters all the parameters but the public exponent
+ * should be parseable bigint objects, the public exponent should be a parseable integer number
+ * @private
+ */
+RSAKey.prototype.hasPrivateKeyProperty = function(obj){
+ obj = obj || {};
+ return obj.hasOwnProperty('n') &&
+ obj.hasOwnProperty('e') &&
+ obj.hasOwnProperty('d') &&
+ obj.hasOwnProperty('p') &&
+ obj.hasOwnProperty('q') &&
+ obj.hasOwnProperty('dmp1') &&
+ obj.hasOwnProperty('dmq1') &&
+ obj.hasOwnProperty('coeff');
+};
+
+/**
+ * Parse the properties of obj in the current rsa object. Obj should AT LEAST
+ * include the modulus and public exponent (n, e) parameters.
+ * @param {Object} obj - the object containing rsa parameters
+ * @private
+ */
+RSAKey.prototype.parsePropertiesFrom = function(obj){
+ this.n = obj.n;
+ this.e = obj.e;
+
+ if (obj.hasOwnProperty('d')){
+ this.d = obj.d;
+ this.p = obj.p;
+ this.q = obj.q;
+ this.dmp1 = obj.dmp1;
+ this.dmq1 = obj.dmq1;
+ this.coeff = obj.coeff;
+ }
+};
+
+/**
+ * Create a new JSEncryptRSAKey that extends Tom Wu's RSA key object.
+ * This object is just a decorator for parsing the key parameter
+ * @param {string|Object} key - The key in string format, or an object containing
+ * the parameters needed to build a RSAKey object.
+ * @constructor
+ */
+var JSEncryptRSAKey = function(key) {
+ // Call the super constructor.
+ RSAKey.call(this);
+ // If a key key was provided.
+ if (key) {
+ // If this is a string...
+ if (typeof key === 'string') {
+ this.parseKey(key);
+ }else if (this.hasPrivateKeyProperty(key)||this.hasPublicKeyProperty(key)) {
+ // Set the values for the key.
+ this.parsePropertiesFrom(key);
+ }
+ }
+};
+
+// Derive from RSAKey.
+JSEncryptRSAKey.prototype = new RSAKey();
+
+// Reset the contructor.
+JSEncryptRSAKey.prototype.constructor = JSEncryptRSAKey;
+
+
+/**
+ *
+ * @param {Object} [options = {}] - An object to customize JSEncrypt behaviour
+ * possible parameters are:
+ * - default_key_size {number} default: 1024 the key size in bit
+ * - default_public_exponent {string} default: '010001' the hexadecimal representation of the public exponent
+ * - log {boolean} default: false whether log warn/error or not
+ * @constructor
+ */
+var JSEncrypt = function(options) {
+ options = options || {};
+ this.default_key_size = parseInt(options.default_key_size) || 1024;
+ this.default_public_exponent = options.default_public_exponent || '010001'; //65537 default openssl public exponent for rsa key type
+ this.log = options.log || false;
+ // The private and public key.
+ this.key = null;
+};
+
+/**
+ * Method to set the rsa key parameter (one method is enough to set both the public
+ * and the private key, since the private key contains the public key paramenters)
+ * Log a warning if logs are enabled
+ * @param {Object|string} key the pem encoded string or an object (with or without header/footer)
+ * @public
+ */
+JSEncrypt.prototype.setKey = function(key){
+ if (this.log && this.key)
+ console.warn('A key was already set, overriding existing.');
+ this.key = new JSEncryptRSAKey(key);
+};
+
+/**
+ * Proxy method for setKey, for api compatibility
+ * @see setKey
+ * @public
+ */
+JSEncrypt.prototype.setPrivateKey = function(privkey) {
+ // Create the key.
+ this.setKey(privkey);
+};
+
+/**
+ * Proxy method for setKey, for api compatibility
+ * @see setKey
+ * @public
+ */
+JSEncrypt.prototype.setPublicKey = function(pubkey) {
+ // Sets the public key.
+ this.setKey(pubkey);
+};
+
+/**
+ * Proxy method for RSAKey object's decrypt, decrypt the string using the private
+ * components of the rsa key object. Note that if the object was not set will be created
+ * on the fly (by the getKey method) using the parameters passed in the JSEncrypt constructor
+ * @param {string} string base64 encoded crypted string to decrypt
+ * @return {string} the decrypted string
+ * @public
+ */
+JSEncrypt.prototype.decrypt = function(string) {
+ // Return the decrypted string.
+ try{
+ return this.getKey().decrypt(b64tohex(string));
+ }catch(ex){
+ return false;
+ }
+};
+
+/**
+ * Proxy method for RSAKey object's encrypt, encrypt the string using the public
+ * components of the rsa key object. Note that if the object was not set will be created
+ * on the fly (by the getKey method) using the parameters passed in the JSEncrypt constructor
+ * @param {string} string the string to encrypt
+ * @return {string} the encrypted string encoded in base64
+ * @public
+ */
+JSEncrypt.prototype.encrypt = function(string) {
+ // Return the encrypted string.
+ try{
+ return hex2b64(this.getKey().encrypt(string));
+ }catch(ex){
+ return false;
+ }
+};
+
+/**
+ * Getter for the current JSEncryptRSAKey object. If it doesn't exists a new object
+ * will be created and returned
+ * @param {callback} [cb] the callback to be called if we want the key to be generated
+ * in an async fashion
+ * @returns {JSEncryptRSAKey} the JSEncryptRSAKey object
+ * @public
+ */
+JSEncrypt.prototype.getKey = function(cb){
+ // Only create new if it does not exist.
+ if (!this.key) {
+ // Get a new private key.
+ this.key = new JSEncryptRSAKey();
+ if (cb && {}.toString.call(cb) === '[object Function]'){
+ this.key.generateAsync(this.default_key_size, this.default_public_exponent,cb);
+ return;
+ }
+ // Generate the key.
+ this.key.generate(this.default_key_size, this.default_public_exponent);
+ }
+ return this.key;
+};
+
+/**
+ * Returns the pem encoded representation of the private key
+ * If the key doesn't exists a new key will be created
+ * @returns {string} pem encoded representation of the private key WITH header and footer
+ * @public
+ */
+JSEncrypt.prototype.getPrivateKey = function() {
+ // Return the private representation of this key.
+ return this.getKey().getPrivateKey();
+};
+
+/**
+ * Returns the pem encoded representation of the private key
+ * If the key doesn't exists a new key will be created
+ * @returns {string} pem encoded representation of the private key WITHOUT header and footer
+ * @public
+ */
+JSEncrypt.prototype.getPrivateKeyB64 = function() {
+ // Return the private representation of this key.
+ return this.getKey().getPrivateBaseKeyB64();
+};
+
+
+/**
+ * Returns the pem encoded representation of the public key
+ * If the key doesn't exists a new key will be created
+ * @returns {string} pem encoded representation of the public key WITH header and footer
+ * @public
+ */
+JSEncrypt.prototype.getPublicKey = function() {
+ // Return the private representation of this key.
+ return this.getKey().getPublicKey();
+};
+
+/**
+ * Returns the pem encoded representation of the public key
+ * If the key doesn't exists a new key will be created
+ * @returns {string} pem encoded representation of the public key WITHOUT header and footer
+ * @public
+ */
+JSEncrypt.prototype.getPublicKeyB64 = function() {
+ // Return the private representation of this key.
+ return this.getKey().getPublicBaseKeyB64();
+};
+