Code Monkey home page Code Monkey logo

cryptico's Introduction

cryptico

Overview

Generating an RSA key pair & public key string

Sam wants to send Matt an encrypted message. In order to do this, he first needs Matt's public key string. A public key pair can be generated for Matt like this:

// The passphrase used to repeatably generate this RSA key.
var PassPhrase = "The Moon is a Harsh Mistress."; 

// The length of the RSA key, in bits.
var Bits = 1024; 

var MattsRSAkey = cryptico.generateRSAKey(PassPhrase, Bits);

Matt's public key string can then be generated like this:

var MattsPublicKeyString = cryptico.publicKeyString(MattsRSAkey);       

and looks like this:

uXjrkGqe5WuS7zsTg6Z9DuS8cXLFz38ue+xrFzxrcQJCXtVccCoUFP2qH/AQ
4qMvxxvqkSYBpRm1R5a4/NdQ5ei8sE8gfZEq7dlcR+gOSv3nnS4/CX1n5Z5m
8bvFPF0lSZnYQ23xlyjXTaNacmV0IuZbqWd4j9LfdAKq5dvDaoE=

Encrypting a message

Matt emails Sam his public key string. Now Sam can encrypt a message for Matt:

var PlainText = "Matt, I need you to help me with my Starcraft strategy.";

var EncryptionResult = cryptico.encrypt(PlainText, MattsPublicKeyString);

EncryptionResult.cipher is the encrypted message, and looks like this:

OOHoAlfm6Viyl7afkUVRoYQv24AfdLnxaay5GjcqpxvEK+dph5kUFZEZIFKo
vVoHoZbtUMekSbMqHQr3wNNpvcNWr4E3DgNLfMZQA1pCAUVmPjNM1ZQmrkKY
HPKvkhmVKaBiYAJGoO/YiFfKnaylLpKOYJZctkZc4wflZcEEqqg=?cJPt71I
HcU5c2LgqGXQKcx2BaAbm25Q2Ku94c933LX5MObL9qbTJEVEv29U0C3gIqcd
qwMV6nl33GtHjyRdHx5fZcon21glUKIbE9P71NwQ=

Decrypting a message

Sam sends his encrypted message to Matt. The message can be decrypted like this:

var CipherText = "OOHoAlfm6Viyl7afkUVRoYQv24AfdLnxaay5GjcqpxvEK+dph5kUFZEZIFKo \
                  vVoHoZbtUMekSbMqHQr3wNNpvcNWr4E3DgNLfMZQA1pCAUVmPjNM1ZQmrkKY \
                  HPKvkhmVKaBiYAJGoO/YiFfKnaylLpKOYJZctkZc4wflZcEEqqg=?cJPt71I \
                  HcU5c2LgqGXQKcx2BaAbm25Q2Ku94c933LX5MObL9qbTJEVEv29U0C3gIqcd \
                  qwMV6nl33GtHjyRdHx5fZcon21glUKIbE9P71NwQ=";

var DecryptionResult = cryptico.decrypt(CipherText, MattsRSAkey);

The decrypted message is in DecryptionResult.plaintext.

Signatures & Public Key IDs

If Sam's RSA key is provided to the cryptico.encrypt function, the message will be signed by him:

var PassPhrase = "There Ain't No Such Thing As A Free Lunch."; 

var SamsRSAkey = cryptico.generateRSAKey(PassPhrase, 1024);

var PlainText = "Matt, I need you to help me with my Starcraft strategy.";

var EncryptionResult = cryptico.encrypt(PlainText, MattsPublicKeyString, SamsRSAkey);

The public key associated with the signature can be used by Matt to make sure that it was sent by Sam, but there are a lot of characters to examine in the key - it would be easy to make a mistake. Instead, the public key string associated with the signature can be processed like this:

var PublicKeyID = cryptico.publicKeyID(EncryptionResult.publickey);

and PublicKeyID would look something like this:

d0bffb0c422dfa3d3d8502040b915248

This shorter key ID can be used to uniquely identify Sam's public key more easily if it must be done manually. Moreover, this key ID can be used by Sam or Matt to make sure they have typed their own passphrases correctly.

API Documentation

RSA Keys

cryptico.generateRSAKey(passphrase, bitlength)

Generates an RSAKey object from a password and bitlength.

passphrase: string from which the RSA key is generated.

bitlength: integer, length of the RSA key (512, 1024, 2048, 4096, 8192).

Returns an RSAKey object.

cryptico.publicKeyString(rsakey)

Returns the public key portion of an RSAKey object in ascii-armored string form, which allows it to be used on websites and in text files without fear of corrupting the public key.

rsakey: An RSAKey object.

Returns an ascii-armored public key string.

cryptico.publicKeyID(publicKeyString)

Returns an MD5 sum of a publicKeyString for easier identification.

publicKeyString: a public key in ascii-armored string form, as generated by the cryptico.publicKeyString function.

Returns an MD5 sum of the public key string.

Encryption

cryptico.encrypt(plaintext, publicKeyString, signingKey)

Encrypts a string with the provided public key. Optionally signs the encrypted string with an RSAKey object.

plaintext: the string to be encrypted.

publicKeyString: The public key string of the recipient.

signingKey: the RSAKey object of the sender.

Returns: status, cipher

status: "success" if encryption succeeded, "failure" if it failed.

cipher: An ascii-armored encrypted message string, optionally signed.

Decryption

cryptico.decrypt(ciphertext, key)

Decrypts an encrypted message with the recipient's RSAKey and verifies the signature, if any.

ciphertext: The encrypted message to be decrypted.

key: The RSAKey object of the recipient.

Returns: status, plaintext, signature, publicKeyString

status: "success" if decryption succeeded, "failure" if it failed. Does not reflect the status of the signature verification.

plaintext: The decrypted message.

signature: "unsigned" if there was no signature, "verified" if it is signed and valid, "forged" if the signature fails verification.

publicKeyString: public key string of the signature (presumably the sender). Returned even if the signature appears to be forged.

Encryption Technical Documentation

Key generation

A hash is generated of the user's passphrase using the SHA256 algorithm found at webtoolkit.info. This hash is used to seed David Bau's seedable random number generator. A (seeded) random RSA key is generated with Tom Wu's RSA key generator with 3 as a hard-coded public exponent.

Encryption

A 32-byte AES key is generated with Tom Wu's random number generator. The plaintext message is converted to a byte string and padded with zeros to 16 bytes round. An initialization vector is created with Tom Wu's random number generator. The AES key is expanded and the plaintext message is encrypted with the Cipher-block chaining mode using the jsaes library. The AES key is encrypted with the recipient's public key using Tom Wu's RSA encryption library.

The encrypted AES key and encrypted message are ascii-armored and concatenated with the "?" character as a delimiter. As an example, here is the result of the phrase "Matt, I need you to help me with my Starcraft strategy." encrypted with the passphrase "The Moon is a Harsh Mistress." used to generate the 1024-bit public key:

EuvU2Ov3gpgM9B1I3VzEgxaAVO/Iy85NARUFZb/h+HrOP72degP0L1fWiHO3
RDm5+kWRaV6oZsn91juJ0L+hrP6BDwlIza9x9DBMEsg3PnOHJENG63RXbu0q
PZd2xDJY70i44sufNqHZ0mui9OdNIeE8FvzEOzMtFGCqDx1Z48s=?K3lOtQC
2w+emoR4W3yvAaslSzTj/ZZIkOu3MNTW8y/OX0OxTKfpsaI6zX6XYrM0MpPr
uw7on1N6VUMpNQO8KUVYl4clquaibKs0marXPFH4=

Signing

When signing the encrypted message, two more pieces of information are attached to the cipher text. The first is the ascii-armored RSA public key of the sender. The second piece of information concatenated with the cipher text is the signature itself, which is generated with the rsa-sign extension by Kenji Urushima, along with the SHA256 algorithm found at webtoolkit.info. These two pieces of code are also used when verifying the signature.

The signature is concatenated with the public key with the string ::52cee64bb3a38f6403386519a39ac91c:: used as the delimiter between the plaintext, the public key of the sender, and the signature:

plaintext
::52cee64bb3a38f6403386519a39ac91c::
public key of sender
::52cee64bb3a38f6403386519a39ac91c::
signature

This concatenated block is then encrypted with CBC AES and concatenated with the encrypted AES key to form the complete encrypted message.

cryptico's People

Contributors

wwwtyro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cryptico's Issues

Getting error "Message too long for RSA (n=32, l=32)"

I'm getting this error in RSAEncrypt when trying to do AES-CBC 256 bit encryption. I think it has to do with the age of the JavaScript engine and use of String.fromCharCode() as it relates to UTF-8 encoding, but I'm not sure.
Any ideas what's wrong?
my code is:
var Bits = 256;
RSAkey = cryptico.generateRSAKey(PassWord, Bits); // PassWord is "12340000000..." 32 characters long
PublicKeyString = cryptico.publicKeyString(RSAkey);
var ret = cryptico.encrypt(ping, PublicKeyString); // fails in here, ping is a JSON (string)

Is it possible to change a RSA key passphrase ?

Hi,

My usecase is that content would be signed with RSA key in order to be verified with the public part of that key. This is the regular use case.
Signing require the passphrase of the private part of the key.

I would like the user to be able to change the passphrase of the key on a regular basis, but the key itself have to remain the same to avoid the need to sign all the old content again and keep the ability to verify signature with the public key.
Is this usecase (signing + change passphrase) possible with your lib ?

Thanks,
Nico.

Add toJSON and fromJSON methods

re: #3 #28

// global deserializer method
RSAKey.fromJSON = function(key) {
    let json = JSON.parse(key);
    if (json.type !== 'RSAKey') return null;
    let rsa = new RSAKey();
    rsa.setPrivateEx(json.n, json.e, json.d, json.p, json.q, json.dmp1, json.dmq1, json.coeff);
    return rsa;
}

// instance serializer, JSON.stringify(object_with_RSAKey) will serialize as expected.
RSAKey.prototype.toJSON = function() {
    return JSON.stringify({
      type: 'RSAKey',
      coeff: this.coeff.toString(16),
      d: this.d.toString(16),
      dmp1: this.dmp1.toString(16),
      dmq1: this.dmq1.toString(16),
      e: this.e.toString(16),
      n: this.n.toString(16),
      p: this.p.toString(16),
      q: this.q.toString(16)
    })
}

Can't encrypt text

I try to encrypt message
var x = cryptico.encrypt("mytext",cryptico.publicKeyString(staticKeys.RSA));
where staticKeys.RSA is RSAKey
And i get error:

aes.js:131 Uncaught TypeError: Cannot read property '177' of undefined
at Object.my.MixColumns (aes.js:131)
at Object.my.Encrypt (aes.js:86)
at Object.my.encryptAESCBC (cryptico.js:3395)
at Object.my.encrypt (cryptico.js:3493)
at HTMLButtonElement.CreateKeysAsker.generator.onclick (script.js:162)
my.MixColumns @ aes.js:131
my.Encrypt @ aes.js:86
my.encryptAESCBC @ cryptico.js:3395
my.encrypt @ cryptico.js:3493
CreateKeysAsker.generator.onclick @ script.js:162

What's wrong?

Get signature of data, without signing it

According to the documentation, when signing some data, the data encrypted with the public key is appended with the encryptor's public key and the signature of the encrypted data, and all of them are again encrypted again with the originator's public key.

In my use case, the originator's public key will be made publicly available, so anyone can create encrypted messages, and also they can sign this messages. Problem is, I want to use public keys as identifiers, and although I want the receiver to be able to open my encrypted (and signed) message, I don't wan't that he knows my public key/identifier if I don't trust him, so I don't want to send the public key/identifier on the message (send the message anonimously), and instead try to get it checking the signature against a list of public keys/identifiers of peers that trust on me.

So, what I'm asking about, is to be able to get the encrypted data and it's signature previously to be packed and encrypted again, so I can be able to send them without the public key.

P.D.: my use case is more complex than this, involving a signature with a permanent public key for identification purposes that it's not transfered anyway and that's the one I want only know the peers whom I have trusted before and have it on their list of public keys/identifiers for (private) identification purposes, and a session public key that's the one that the messages are encrypted and signed for authentication purposes.

is generateRSAKey() deterministic?

From the documentation, it is not entirely clear wether the generateRSAKey() function is determinitic or not.
Meaning, if I use the same PassPhrase and Bits values, am I ensured that the generated RSAkey would always be the same or can it be different from one call to the function to another?

License

Hi, just curious what this library is licensed under?

thanks!

store javascript object rsa private key

Hi,
Is there a way to store the private key object in a javascript session? I've tried JSON.stringify, but when I parse the object, the decryption fails. The object seems to lose part of the object.

Thanks,
Jason

cryptico for native ios application

Hello developer,

Thanks for creating this library. One of my project use this library and do encryption for hybrid app. Problem is now I need to create with native application and I don't see any similar library to use. Is there a way to call this library from native code? Or is there any similar library that you know?

Can I decrypt with public key only or without storing passphrase in app

Hey I'm a little confused about how I should proceed with my application and using this library:

I have a web application running on a site with a unique ID. The application takes the ID, plays around with it and calls that a challenge_code.

The challenge _code is sent to me (user emails it to me). I encrypt it and call it a license_key. I send that to the application user and he enters the key into the application.

When the app loads, I need to decrypt the key back into the challenge_code and ensure that it matches the challenge_code the application would generate.

I'm not sure what I need to store in the application and what I need to keep on my end of things to ensure that this process works reliably, if at all.

Is it possible to decrypt in the application using only the PublicKey String? I'm trying to avoid storing the passphrase in code.

Node.js support

Is cryptico compatile with Node.js? If so, I would add a package.json file and push it to the NPM registry, and if not, I would add support for it since it's a lot far easier to use that native crypto libraries.

sign without encrypt?

Is it possible to just sign a message without encrypt it?
Just for sender verification at recipients side?

Bug in RSA encription?

I am not an expert at all in cryptography. As far as I
understand, the output of rsa encryption (for a small enough message)
ought to be of a fixed length. For example with 512 bits keys the
output ought to be 64 bytes, but the following test is consistently
able to produce 63 bytes ciphertexts that decrypt correctly. Is this
normal or a bug?

function test() {
    var k = cryptico.generateRSAKey("",512), i = 0, max = Math.pow(2,12);
    var ciphertext = k.encrypt("");
    while (i < max && ciphertext.length == 128) {
        ciphertext = k.encrypt("");
        i++;
    }
    if (i < max) console.log("Error at iteration " + i + ":
           ciphertext length = " + ciphertext.length + "; ciphertext = " +
            ciphertext);
    return { key : k, ciphertext : ciphertext};
}

Do not support UTF-8

plaintext: "Mưa nắng là chuyện của mày, tao đéo quan tâm!!! Được không hả?"

after encrypt & decrypt: "MLa nZng là chuy�n c�a mày, tao ¢éo quan tâm!!! ��Sc không hÈ?"

Wrong example

In the README.md and test.html, its used the function cryptico.generateRSAKey(PassPhrase, Bits);
this not exists in rsa.js
maybe function RSAGenerate(B, E)

Storable/copyable private key?

How would I store the private key for later decryption? I can easily transfer the public key string, but I don't want to store the RSA key anywhere on a server. However, a user can't just copy the RSA key as text, so how would they retain the private key locally for later decryption?

Can there be a way to convert the private key into something copy-able like base64?

Encrypt message with private key

Is there a way to encrypt a message with the private key?

Scenario -- The public key of recipients is unknown, but the originator needs to be verified by all recipients via a 'token' of some sort. The message would be decrypted by the peers with the originators public key -- this decrypted token is then verified against a matching plaintext token, thus verifying the identity of the originator.

Thanks!

what is compiler.jar?

its not required to make the test example works, it was used during the production of the other js files?

a bug in library

    var aeskey = key.decrypt(my.b64to16(cipherblock[0]));

TypeError: key.decrypt is not a function

In jsbn, what is the correct function of variable DV?

in jsbn.js file

// (protected) set from integer value x, -DV <= x < DV

function bnpFromInt(x) {
this.t = 1;
this.s = (x < 0) ? -1 : 0;
if (x > 0) this[0] = x;
else if (x < -1) this[0] = x + DV;
else this.t = 0;
}

what is the correct function of variable DV?, i mean, DV -> this.DV? or x.DV? or the function is correct?

Protocol issues

There seem to be some issues with this protocol.

You seem to sign before encryption, which makes you vulnerable to padding oracle attacks.

Furthermore, you send you public key with the signed message. But this makes no sense, as the receiver has no method of trusting the public key.

Other than that, please be aware that performing encryption/signing in JavaScript may not make sense as the JavaScript code itself cannot be trusted. So you need to at least require the use of TLS/SSL.

In your signing paragraph, you say that you attach information to the ciphertext but you end up adding information to the plaintext.

That said, the documentation of your project is very readable.

Please don't redefine Math.random() to be non random

Hey wwwtyro,

I'm a developer of 3rd party JavaScript tools that my customers install on their websites. I ran across cryptico, while debugging why my tools broke on my customer's website. The customer had installed cryptico, and it had redefined the global function Math.random() to be non-random.

We all share the global namespace. Could you please reconsider this approach as it breaks the functionality of other scripts on the page that rely on Math.random() to be pseudo-random.

[enhancement] Add missing bower.json.

Hey, maintainer(s) of wwwtyro/cryptico!

We at VersionEye are working hard to keep up the quality of the bower's registry.

We just finished our initial analysis of the quality of the Bower.io registry:

7530 - registered packages, 224 of them doesnt exists anymore;

We analysed 7306 existing packages and 1070 of them don't have bower.json on the master branch ( that's where a Bower client pulls a data ).

Sadly, your library wwwtyro/cryptico is one of them.

Can you spare 15 minutes to help us to make Bower better?

Just add a new file bower.json and change attributes.

{
  "name": "wwwtyro/cryptico",
  "version": "1.0.0",
  "main": "path/to/main.css",
  "description": "please add it",
  "license": "Eclipse",
  "ignore": [
    ".jshintrc",
    "**/*.txt"
  ],
  "dependencies": {
    "<dependency_name>": "<semantic_version>",
    "<dependency_name>": "<Local_folder>",
    "<dependency_name>": "<package>"
  },
  "devDependencies": {
    "<test-framework-name>": "<version>"
  }
}

Read more about bower.json on the official spefication and nodejs semver library has great examples of proper versioning.

NB! Please validate your bower.json with jsonlint before commiting your updates.

Thank you!

Timo,
twitter: @versioneye
email: [email protected]
VersionEye - no more legacy software!

bnpFromNumber logical bug

Bug location

file cryptico/lib/cryptico.js at line 749

function bnpFromNumber(a, b, c) {
    if ("number" == typeof b) {
        // new BigInteger(int,int,RNG)
        if (a < 2) this.fromInt(1);
        else {
            this.fromNumber(a, c);
            if (!this.testBit(a - 1)) // force MSB set
            this.bitwiseTo(BigInteger.ONE.shiftLeft(a - 1), op_or, this);
            if (this.isEven()) this.dAddOffset(1, 0); // force odd
            while (!this.isProbablePrime(b)) {
                this.dAddOffset(2, 0);
                if (this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a - 1), this);
            }
        }
    }
    else {
        // new BigInteger(int,RNG)
        var x = new Array(),
            t = a & 7;
        x.length = (a >> 3) + 1;
        b.nextBytes(x);
        if (t > 0) x[0] &= ((1 << t) - 1);
        else x[0] = 0;
        this.fromString(x, 256);
    }
}

Explanation

If the argument b is of type number, it will crash when running line 769 b.nextBytes(x) since number don't have method nextBytes/1

Steps to product the bug

var key = cryptico.generateRSAKey("test",2048);
key.generate(2048,3)

test case output

> key = lib.default.generateRSAKey("test",2048); key.generate(2048,3)
TypeError: Cannot read property 'nextBytes' of undefined
    at BigInteger.bnpFromNumber [as fromNumber] (/home/beenotung/workspace/github.com/beenotung/typestub-cryptico/node_modules/cryptico/lib/cryptico.js:769:10)
    at BigInteger.bnpFromNumber [as fromNumber] (/home/beenotung/workspace/github.com/beenotung/typestub-cryptico/node_modules/cryptico/lib/cryptico.js:754:18)
    at new BigInteger (/home/beenotung/workspace/github.com/beenotung/typestub-cryptico/node_modules/cryptico/lib/cryptico.js:12:51)
    at RSAKey.RSAGenerate [as generate] (/home/beenotung/workspace/github.com/beenotung/typestub-cryptico/node_modules/cryptico/lib/cryptico.js:2228:14)
    at repl:1:52
    at ContextifyScript.Script.runInThisContext (vm.js:50:33)
    at REPLServer.defaultEval (repl.js:239:29)
    at bound (domain.js:301:14)
    at REPLServer.runBound [as eval] (domain.js:314:12)
    at REPLServer.onLine (repl.js:440:10)

Decrypt on Server Side

Hello,
Would like to ask if it is possible to encrypt on the client side using cryptico and decrypt on the server side (like using C#).

Thanks

Cryptico for hybrid mobile apps

We are using cryptico for nativescript application. The decryption logic works fine on android however for ios it slows usually takes minutes. We narrowed down the issue to our RSA key generation.

Any help.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.