keyczar.js
function _makeKeyczar(data, password) {
    var instance = {};

    instance.metadata = JSON.parse(data.meta);
    if (instance.metadata.encrypted !== false) {
        if (!password) {
            throw new Error('Key is encrypted; you must provide the password');
        }
        if (password.length === 0) {
            throw new Error('Must supply a password length > 0');
        }
    } else if (password) {
        throw new Error('Key is not encrypted but password provided');
    }

    var primaryVersion = _getPrimaryVersion(instance.metadata);
    var primaryKeyString = data[String(primaryVersion)];
    if (instance.metadata.encrypted) {
        primaryKeyString = _decryptKey(primaryKeyString, password);
    }

    var t = instance.metadata.type;
    var p = instance.metadata.purpose;
    if (t == keyczar.TYPE_RSA_PRIVATE) {
        instance.primary = keyczar_util.privateKeyFromKeyczar(primaryKeyString);
        instance.exportPublicKey = function() { return _exportPublicKey(instance); };
    } else if (t == keyczar.TYPE_RSA_PUBLIC) {
        instance.primary = keyczar_util.publicKeyFromKeyczar(primaryKeyString);
    } else if (t == keyczar.TYPE_AES && p == keyczar.PURPOSE_DECRYPT_ENCRYPT) {
        instance.primary = keyczar_util.aesFromKeyczar(primaryKeyString);
    } else {
        throw new Error('Unsupported key type: ' + t);
    }

    if (p == keyczar.PURPOSE_ENCRYPT || p == keyczar.PURPOSE_DECRYPT_ENCRYPT) {
        // Takes a raw byte string, returns a raw byte string
        instance.encryptBinary = function(plaintext) {
            // TODO: assert that plaintext does not contain special characters
            return instance.primary.encrypt(plaintext);
        };

        instance.encrypt = function(plaintext) {
            // encode as UTF-8 in case plaintext contains non-ASCII characters
            plaintext = forge.util.encodeUtf8(plaintext);
            var message = instance.encryptBinary(plaintext);
            message = keyczar_util.encodeBase64Url(message);
            return message;
        };

        // only include decryption if supported by this key type
        if (p == keyczar.PURPOSE_DECRYPT_ENCRYPT) {
            instance.decryptBinary = function(message) {
                return instance.primary.decrypt(message);
            };

            instance.decrypt = function(message) {
                message = keyczar_util.decodeBase64Url(message);
                var plaintext = instance.primary.decrypt(message);
                plaintext = forge.util.decodeUtf8(plaintext);
                return plaintext;
            };
        }
    } else if (p == keyczar.PURPOSE_VERIFY || p == keyczar.PURPOSE_SIGN_VERIFY) {
        instance.verify = function(message, signature) {
            message = forge.util.encodeUtf8(message);
            signature = keyczar_util.decodeBase64Url(signature);
            return instance.primary.verify(message, signature);
        };

        if (p == keyczar.PURPOSE_SIGN_VERIFY) {
            instance.sign = function(message) {
                message = forge.util.encodeUtf8(message);
                var signature = instance.primary.sign(message);
                return keyczar_util.encodeBase64Url(signature);
            };
        }
    }

    var _toJsonObject = function() {
        var out = {};
        out.meta = JSON.stringify(instance.metadata);

        // TODO: Store and serialize ALL keys. For now this works
        if (instance.metadata.versions.length != 1) {
            throw new Error('TODO: Support keyczars with multiple keys');
        }
        var primaryVersion = _getPrimaryVersion(instance.metadata);
        out[String(primaryVersion)] = instance.primary.toJson();
        return out;
    };

    // Returns the JSON serialization of this keyczar instance.
    instance.toJson = function() {
        if (instance.metadata.encrypted) {
            throw new Error('Key is encrypted; use toJsonEncrypted() instead');
        }
        var out = _toJsonObject();
        return JSON.stringify(out);
    };

    // Returns the decrypted version of this password-protected key.
    // WARNING: This is dangerous as it can be used to leak a password-protected key
    instance.exportDecryptedJson = function() {
        if (!instance.metadata.encrypted) {
            throw new Error('Key is not encrypted; use toJson() instead');
        }

        var unencrypted = _toJsonObject();

        // hack the metadata to mark it as unencrypted
        var meta = JSON.parse(unencrypted.meta);
        meta.encrypted = false;
        unencrypted.meta = JSON.stringify(meta);
        return JSON.stringify(unencrypted);
    };

    instance.toJsonEncrypted = function(password) {
        // TODO: Enforce some sort of minimum length?
        if (password.length === 0) {
            throw new Error('Password length must be > 0');
        }

        // get the unencrypted JSON object
        var unencrypted = _toJsonObject();

        // set metadata.encrypted = true
        var meta = JSON.parse(unencrypted.meta);
        meta.encrypted = true;
        unencrypted.meta = JSON.stringify(meta);

        // encrypt each key
        for (var property in unencrypted) {
            if (property == 'meta') continue;
            unencrypted[property] = _encryptKey(unencrypted[property], password);
        }

        return JSON.stringify(unencrypted);
    };

    return instance;
}
function _makeKeyczar(data, password) {
    var instance = {};

    instance.metadata = JSON.parse(data.meta);
    if (instance.metadata.encrypted !== false) {
        if (!password) {
            throw new Error('Key is encrypted; you must provide the password');
        }
        if (password.length === 0) {
            throw new Error('Must supply a password length > 0');
        }
    } else if (password) {
        throw new Error('Key is not encrypted but password provided');
    }

    var primaryVersion = _getPrimaryVersion(instance.metadata);
    var primaryKeyString = data[String(primaryVersion)];
    if (instance.metadata.encrypted) {
        primaryKeyString = _decryptKey(primaryKeyString, password);
    }

    var t = instance.metadata.type;
    var p = instance.metadata.purpose;
    if (t == keyczar.TYPE_RSA_PRIVATE) {
        instance.primary = keyczar_util.privateKeyFromKeyczar(primaryKeyString);
        instance.exportPublicKey = function() { return _exportPublicKey(instance); };
    } else if (t == keyczar.TYPE_RSA_PUBLIC) {
        instance.primary = keyczar_util.publicKeyFromKeyczar(primaryKeyString);
    } else if (t == keyczar.TYPE_AES && p == keyczar.PURPOSE_DECRYPT_ENCRYPT) {
        instance.primary = keyczar_util.aesFromKeyczar(primaryKeyString);
    } else {
        throw new Error('Unsupported key type: ' + t);
    }

    if (p == keyczar.PURPOSE_ENCRYPT || p == keyczar.PURPOSE_DECRYPT_ENCRYPT) {
        // Takes a raw byte string, returns a raw byte string
        instance.encryptBinary = function(plaintext) {
            // TODO: assert that plaintext does not contain special characters
            return instance.primary.encrypt(plaintext);
        };

        instance.encrypt = function(plaintext) {
            // encode as UTF-8 in case plaintext contains non-ASCII characters
            plaintext = forge.util.encodeUtf8(plaintext);
            var message = instance.encryptBinary(plaintext);
            message = keyczar_util.encodeBase64Url(message);
            return message;
        };

        // only include decryption if supported by this key type
        if (p == keyczar.PURPOSE_DECRYPT_ENCRYPT) {
            instance.decryptBinary = function(message) {
                return instance.primary.decrypt(message);
            };

            instance.decrypt = function(message) {
                message = keyczar_util.decodeBase64Url(message);
                var plaintext = instance.primary.decrypt(message);
                plaintext = forge.util.decodeUtf8(plaintext);
                return plaintext;
            };
        }
    } else if (p == keyczar.PURPOSE_VERIFY || p == keyczar.PURPOSE_SIGN_VERIFY) {
        instance.verify = function(message, signature) {
            message = forge.util.encodeUtf8(message);
            signature = keyczar_util.decodeBase64Url(signature);
            return instance.primary.verify(message, signature);
        };

        if (p == keyczar.PURPOSE_SIGN_VERIFY) {
            instance.sign = function(message) {
                message = forge.util.encodeUtf8(message);
                var signature = instance.primary.sign(message);
                return keyczar_util.encodeBase64Url(signature);
            };
        }
    }

    var _toJsonObject = function() {
        var out = {};
        out.meta = JSON.stringify(instance.metadata);

        // TODO: Store and serialize ALL keys. For now this works
        if (instance.metadata.versions.length != 1) {
            throw new Error('TODO: Support keyczars with multiple keys');
        }
        var primaryVersion = _getPrimaryVersion(instance.metadata);
        out[String(primaryVersion)] = instance.primary.toJson();
        return out;
    };

    // Returns the JSON serialization of this keyczar instance.
    instance.toJson = function() {
        if (instance.metadata.encrypted) {
            throw new Error('Key is encrypted; use toJsonEncrypted() instead');
        }
        var out = _toJsonObject();
        return JSON.stringify(out);
    };

    // Returns the decrypted version of this password-protected key.
    // WARNING: This is dangerous as it can be used to leak a password-protected key
    instance.exportDecryptedJson = function() {
        if (!instance.metadata.encrypted) {
            throw new Error('Key is not encrypted; use toJson() instead');
        }

        var unencrypted = _toJsonObject();

        // hack the metadata to mark it as unencrypted
        var meta = JSON.parse(unencrypted.meta);
        meta.encrypted = false;
        unencrypted.meta = JSON.stringify(meta);
        return JSON.stringify(unencrypted);
    };

    instance.toJsonEncrypted = function(password) {
        // TODO: Enforce some sort of minimum length?
        if (password.length === 0) {
            throw new Error('Password length must be > 0');
        }

        // get the unencrypted JSON object
        var unencrypted = _toJsonObject();

        // set metadata.encrypted = true
        var meta = JSON.parse(unencrypted.meta);
        meta.encrypted = true;
        unencrypted.meta = JSON.stringify(meta);

        // encrypt each key
        for (var property in unencrypted) {
            if (property == 'meta') continue;
            unencrypted[property] = _encryptKey(unencrypted[property], password);
        }

        return JSON.stringify(unencrypted);
    };

    return instance;
}
function _makeKeyczar ( data , password ) { var instance = { } ; instance . metadata = JSON . parse ( data . meta ) ; if ( instance . metadata . encrypted !== false ) { if ( ! password ) { throw new Error ( 'Key is encrypted; you must provide the password' ) ; } if ( password . length === 0 ) { throw new Error ( 'Must supply a password length > 0' ) ; } } else if ( password ) { throw new Error ( 'Key is not encrypted but password provided' ) ; } var primaryVersion = _getPrimaryVersion ( instance . metadata ) ; var primaryKeyString = data [ String ( primaryVersion ) ] ; if ( instance . metadata . encrypted ) { primaryKeyString = _decryptKey ( primaryKeyString , password ) ; } var t = instance . metadata . type ; var p = instance . metadata . purpose ; if ( t == keyczar . TYPE_RSA_PRIVATE ) { instance . primary = keyczar_util . privateKeyFromKeyczar ( primaryKeyString ) ; instance . exportPublicKey = function ( ) { return _exportPublicKey ( instance ) ; } ; } else if ( t == keyczar . TYPE_RSA_PUBLIC ) { instance . primary = keyczar_util . publicKeyFromKeyczar ( primaryKeyString ) ; } else if ( t == keyczar . TYPE_AES && p == keyczar . PURPOSE_DECRYPT_ENCRYPT ) { instance . primary = keyczar_util . aesFromKeyczar ( primaryKeyString ) ; } else { throw new Error ( 'Unsupported key type: ' + t ) ; } if ( p == keyczar . PURPOSE_ENCRYPT || p == keyczar . PURPOSE_DECRYPT_ENCRYPT ) { // Takes a raw byte string, returns a raw byte string instance . encryptBinary = function ( plaintext ) { // TODO: assert that plaintext does not contain special characters return instance . primary . encrypt ( plaintext ) ; } ; instance . encrypt = function ( plaintext ) { // encode as UTF-8 in case plaintext contains non-ASCII characters plaintext = forge . util . encodeUtf8 ( plaintext ) ; var message = instance . encryptBinary ( plaintext ) ; message = keyczar_util . encodeBase64Url ( message ) ; return message ; } ; // only include decryption if supported by this key type if ( p == keyczar . PURPOSE_DECRYPT_ENCRYPT ) { instance . decryptBinary = function ( message ) { return instance . primary . decrypt ( message ) ; } ; instance . decrypt = function ( message ) { message = keyczar_util . decodeBase64Url ( message ) ; var plaintext = instance . primary . decrypt ( message ) ; plaintext = forge . util . decodeUtf8 ( plaintext ) ; return plaintext ; } ; } } else if ( p == keyczar . PURPOSE_VERIFY || p == keyczar . PURPOSE_SIGN_VERIFY ) { instance . verify = function ( message , signature ) { message = forge . util . encodeUtf8 ( message ) ; signature = keyczar_util . decodeBase64Url ( signature ) ; return instance . primary . verify ( message , signature ) ; } ; if ( p == keyczar . PURPOSE_SIGN_VERIFY ) { instance . sign = function ( message ) { message = forge . util . encodeUtf8 ( message ) ; var signature = instance . primary . sign ( message ) ; return keyczar_util . encodeBase64Url ( signature ) ; } ; } } var _toJsonObject = function ( ) { var out = { } ; out . meta = JSON . stringify ( instance . metadata ) ; // TODO: Store and serialize ALL keys. For now this works if ( instance . metadata . versions . length != 1 ) { throw new Error ( 'TODO: Support keyczars with multiple keys' ) ; } var primaryVersion = _getPrimaryVersion ( instance . metadata ) ; out [ String ( primaryVersion ) ] = instance . primary . toJson ( ) ; return out ; } ; // Returns the JSON serialization of this keyczar instance. instance . toJson = function ( ) { if ( instance . metadata . encrypted ) { throw new Error ( 'Key is encrypted; use toJsonEncrypted() instead' ) ; } var out = _toJsonObject ( ) ; return JSON . stringify ( out ) ; } ; // Returns the decrypted version of this password-protected key. // WARNING: This is dangerous as it can be used to leak a password-protected key instance . exportDecryptedJson = function ( ) { if ( ! instance . metadata . encrypted ) { throw new Error ( 'Key is not encrypted; use toJson() instead' ) ; } var unencrypted = _toJsonObject ( ) ; // hack the metadata to mark it as unencrypted var meta = JSON . parse ( unencrypted . meta ) ; meta . encrypted = false ; unencrypted . meta = JSON . stringify ( meta ) ; return JSON . stringify ( unencrypted ) ; } ; instance . toJsonEncrypted = function ( password ) { // TODO: Enforce some sort of minimum length? if ( password . length === 0 ) { throw new Error ( 'Password length must be > 0' ) ; } // get the unencrypted JSON object var unencrypted = _toJsonObject ( ) ; // set metadata.encrypted = true var meta = JSON . parse ( unencrypted . meta ) ; meta . encrypted = true ; unencrypted . meta = JSON . stringify ( meta ) ; // encrypt each key for ( var property in unencrypted ) { if ( property == 'meta' ) continue ; unencrypted [ property ] = _encryptKey ( unencrypted [ property ] , password ) ; } return JSON . stringify ( unencrypted ) ; } ; return instance ; }
Returns a Keyczar object from data. 
@param {*} data Deserialized JSON object containing the key
@param {string=} password Used to encrypt the key
Returns a Keyczar object from data .