
CryptDown – Client-side AES-encrypted Markdown pastes - ikkez
https://cryptdown.eu/
======
gose1
[https://cryptdown.eu/view/23mz2dmpdq5co](https://cryptdown.eu/view/23mz2dmpdq5co)
\- password: lolz

and this is why we don't like crypto in the browser...

~~~
dsacco
This is a cross-site scripting vulnerability, yes, but client-side crypto does
not necessitate cross-site scripting.

This implementation just so happens to not protect against it properly. There
are legitimate arguments against client-side cryptography; this is not one of
them.

~~~
jacksingleton
The argument is that implementing crypto within an application that is
designed to download and execute untrusted code from untrusted servers and has
an extremely large attack service [1] is a difficult if not dangerous task.

[1] your browser

~~~
kragen
While that may be true, that’s a different class of vulnerabilities that
doesn’t include XSS.

------
ikkez
It's open source now:
[https://github.com/ikkez/CryptDown](https://github.com/ikkez/CryptDown) feel
free to add your own ideas and improvements.

~~~
dsacco
Hey, cool project. As another poster in this thread mentioned, you have a
cross-site scripting vulnerability because you don't properly sanitize the
decrypted user input.

I might work on this if I get a little time later today, but in case I don't,
here are a few resources for you:

[http://stackoverflow.com/questions/3129899/what-are-the-
comm...](http://stackoverflow.com/questions/3129899/what-are-the-common-
defenses-against-xss)

[https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%...](https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet)

The good news is that PHP is so widespread that there are really great
tutorials and libraries for sanitizing user input and preventing cross-site
scripting.

Good luck!

~~~
ikkez
should be fixed now.

------
ikeboy
A quick search turns up [http://0bin.net/](http://0bin.net/),
[https://cryptbin.com/](https://cryptbin.com/),
[https://cryptobin.org](https://cryptobin.org),
[https://defuse.ca/pastebin.htm](https://defuse.ca/pastebin.htm),
[https://paste.sh](https://paste.sh),
[http://sebsauvage.net/paste/](http://sebsauvage.net/paste/), and
[https://pastee.org/about](https://pastee.org/about).

Is there anything new in your implementation, or is this just "me too"?

~~~
Someone1234
None of those have a WYSIWYG editor for markdown, and no markdown renderer. So
I'd call those the USP rather than the encryption in and of itself.

~~~
ikeboy
[https://cryptbin.com/](https://cryptbin.com/) does markdown, but not WYSIWYG.

------
paul-sh
Ikkez, you use hash == HMAC-SHA256(CT, SHA256(password)) to check if the
password is valid. You should replace the "SHA256(password)" part here with a
strong password-based key derivation function (PBKDF2, scrypt, bcrypt) with a
decent number of iterations.

SHA256 is blazing fast. While this is a good thing for a hash function in
general, it is not for a key derivation. PBKDF2, scrypt, bcrypt and others are
slow by design to make an attack much harder.

~~~
ikkez
I think it does not matter that much here, as this hash is just used for
checking the message integrity. This hash is build from the encrypted doc +
the hashed password. if you are about to brute force the HMAC function, you
would just get a SHA hash back. It would make more sense to try to break the
message directly. I got this trick from
[http://stackoverflow.com/a/23190781/2038179](http://stackoverflow.com/a/23190781/2038179)

~~~
paul-sh
I think you use this to validate the password, not to check the integrity of
the message. And an attacker gets a password as a result of brute-forcing, not
a hash. Look at this snippet in pseudocode:

    
    
        // Get the hash and the encrypted text from the encrypted data
        hash = substing(encryptedData, 0, 64);
        encryptedText = substing(encryptedData, 64);
    
        foreach password in PasswordDictionary {
          if hash == HMAC(encryptedText, SHA256(password)) {
            print "Password found: " + password;
            // Decrypt the message 
            print "Message: " + AESDecrypt(encryptedText, password);
          }
        }
    

The loop will run fast, and you get a clear-text password as a result, which
can decrypt the message. If you replace SHA256(password) with PBKDF2(password,
20000) the loop becomes insanely slower.

~~~
tracker1
that assumes an async pbkdf2 implementation for the browser... most browser
implementations for crypto I've seen are synchronous, though I'm uncertain
today, I haven't checked for a couple years now. In the case of synchronous,
most browser based variants will kill the script before it completes... you
could use workers, but that won't work for ie<=9 [1]. Which may or may not be
an option here. As it stands, it would be a nice options.

I really like the markdown editor implementation, will look at how they are
using medium-editor... I'm working on a similar implementation and was
considering going side-by-side, but this actually looks/works better. I did
write a sanitization utility[2] for such inputs, but hadn't yet completed the
editor.

[1] [http://caniuse.com/#feat=webworkers](http://caniuse.com/#feat=webworkers)
[2] [https://www.npmjs.com/package/cc-text-
utils](https://www.npmjs.com/package/cc-text-utils)

------
sarciszewski
If you're not shipping your cryptography in a browser extension, npm module,
etc. then you might as well not implement the cryptography features.

[http://matasano.com/articles/javascript-
cryptography/](http://matasano.com/articles/javascript-cryptography/)

~~~
lewisl9029
The WebCrypto API is meant to solve this but many aspects of it are not quite
ready for production yet.

I'd personally love to see JS crypto libraries like CryptoJS, SJCL and Forge
start implementing polyfills for WebCrypto. Even just using the
getRandomValues method (which seems to be fairly stable across all modern
browsers) for their PRNG implementations would result in a much more
theoretically sound crypto library.

[http://www.w3.org/TR/WebCryptoAPI/](http://www.w3.org/TR/WebCryptoAPI/)

[https://github.com/digitalbazaar/forge](https://github.com/digitalbazaar/forge)

[https://github.com/bitwiseshiftleft/sjcl](https://github.com/bitwiseshiftleft/sjcl)

[https://code.google.com/p/crypto-js/](https://code.google.com/p/crypto-js/)

~~~
tracker1
I'd like to see more async implementations of crypto for JS, breaking work up
with setTimeout/setImmediate so that they don't kill the browser... Lately,
I'm more inclinded to first reach for the browserify polyfills, and use the
node crypto api.

------
fabulist
Nice. I have a CLI for a similar site (kopy.io); do you mind if I add support
for your site as well?

My project is here:

github.com/xmnr/kopycat

It boasts a single user right now, so it shouldn't burden you with traffic too
much.

~~~
ikkez
yeah cool, why not. The code is on github now.

~~~
fabulist
Sweet, thanks

------
adventured
You should have a prominent "clear" action button, to wipe the pre-loaded
example content with a click. I tried clicking on "Create New" in the upper
right hoping that would generate that effect, but it just resets it all back.
I think a 'clear content' button would be especially nice for mobile.

------
jknz
The WYSIWYG editor is really nice. I'm wondering if it is home-made or if it
comes from a library?

~~~
someone13
This appears to be [https://github.com/daviferreira/medium-
editor](https://github.com/daviferreira/medium-editor)

------
paul-sh
You shouldn't have minified the code, let people check what's going on.

~~~
ikkez
good point. I reverted the minification, but will put it back once I published
the whole code on github. thx

~~~
Fastidious
Going to open source it?

~~~
nacs
Author has open sourced it now:
[https://github.com/ikkez/CryptDown](https://github.com/ikkez/CryptDown)

------
Fastidious
Interesting! Other than JS, what else runs on the backend?

~~~
ikkez
backend is driven by PHP Fat-Free Framework
([http://fatfreeframework.com](http://fatfreeframework.com)), as stated in the
info window ;)

~~~
Fastidious
Duh! I missed that one, amongst so many JS ones. My mistake. Thanks!

------
Buge
>Nobody can help you when you loose an encryption password

*lose

