Hacker News new | past | comments | ask | show | jobs | submit | more cryptbe's comments login

Interesting coincidence. I just wrote http://vnhacker.blogspot.com/2014/06/why-javascript-crypto-i..., in which I explain the threat model implied in the Matasano's article doesn't apply to most applications.


"they just make the task of programming a crypto library a bit more fun and challenging, not riskier"

Seriously? It makes it more difficult to get things right, but the risk of getting it wrong is not increased? And that after you just described how the challenges of JS have already directly led to vulnerabilities?

Also, you mostly don't really support your own argument. How exactly does a malicious server not affect "crypto browser apps"? How does staying out of scope for PCI DSS have anything to do with security (except maybe demonstrating that PCI DSS is crap because it can so easily be circumvented)? Also, in what kind of scenario would leaking info in a referer be a problem, but leaking the same info in encrypted form would not? And how do you guarantee that your verification code is loaded fresh from the server once your application has been compromised in a browser?


> Seriously? It makes it more difficult to get things right, but the risk of getting it wrong is not increased? And that after you just described how the challenges of JS have already directly led to vulnerabilities?

Well it seems that you misunderstood which challenges I was talking about. Lack of types is a big problem, but besides that everything else doesn't make the risk bigger.

> How exactly does a malicious server not affect "crypto browser apps"?

I didn't claim that malicious servers won't be able to affect crypto browser apps. What I said is that in these apps you have to trust the server already, so it doesn't make sense to consider them untrusted.

> How does staying out of scope for PCI DSS have anything to do with security (except maybe demonstrating that PCI DSS is crap because it can so easily be circumvented)?

It's exactly the point. When people say "javavascript crypto is harmful" they don't consider use cases where it's really useful, even just to circumvent PCI DSS.

> Also, in what kind of scenario would leaking info in a referer be a problem, but leaking the same info in encrypted form would not?

I don't understand this question.

> And how do you guarantee that your verification code is loaded fresh from the server once your application has been compromised in a browser?

Because every time I refresh my browser I get a chance to get some trusted code from the server.


> Well it seems that you misunderstood which challenges I was talking about. Lack of types is a big problem, but besides that everything else doesn't make the risk bigger.

So, it isn't actually a bit more challenging then?

Also, it seems to me like you are at least forgetting timing and possibly other side channels.

> I don't understand this question.

I just can't see any actual scenario where that helps, mostly because it seems to me that the cipher text usually would be a plain-text equivalent, so it doesn't really matter to the attacker whether they have the plain text or the cipher text.

> Because every time I refresh my browser I get a chance to get some trusted code from the server.

So, in other words, you don't have a guarantee?

Other than that, and in general, it seems to me that your argument is somewhat of an equivocation fallacy: You are essentially redefining crypto to include kinda-non-crypto, to then claim that this redefined crypto actually can sensibly be used in browser-side JS, and therefore the arguments against the use of the original crypto are somehow not good advice.

I would think that it is rather obviously implied in most criticism of JS crypto that you are not just executing code that performs a cryptographic primitive, but that you are actually using it to achieve some security goal, and in particular that you are using client-side JS rather than some server-side crypto for some security advantage. That is essentially the implied vague threat model.

So, yeah, it's true that there are uses for crypto primitives that aren't affected by that threat model, because they aren't about security at all. And others that are less affected for various reasons. But it's highly misleading to therefore claim that "most applications aren't affected by that threat model". I'd think that most applications actually are. Except for those built by people who do understand enough of cryptography to not need posts such as the one by matasano. That is to say: Yes, once you yourself can write such an FAQ, you might be able to make use of JS crypto. But at that point, that post won't keep you from doing it anyhow. If you can't, though, chances are you first need to understand every single point made in it.


> So, it isn't actually a bit more challenging then?

More challenging, yes. Riskier, no.

I don't like that Javascript doesn't have native support for big integers (like Python does), or that it stores numbers as floating points in a 52-bit mantissa, but I fail to see why this makes developing crypto code riskier.

> Also, it seems to me like you are at least forgetting timing and possibly other side channels.

Well, I ain't. When you don't control the instructions being executed by the CPU you may have the risks of security-sensitive information leaks. This applies not only to Javascript, but also to all scripting languages. I could say that it also applies to Java, if the methods in its BigInteger class aren't fixed-timing.

In other words using Javascript doesn't make the problem any worse. If you disagree, you're invited to take a look at End-To-End, find a side-channel leak and write an exploit for it. You could earn serious cold cash with that finding.

> I just can't see any actual scenario where that helps, mostly because it seems to me that the cipher text usually would be a plain-text equivalent, so it doesn't really matter to the attacker whether they have the plain text or the cipher text.

I described where it helps in my article.

Re your last point: if doing SSH in a browser isn't crypto I don't know what could be. Is the only thing you consider Javascript crypto encrypted webmail? That's your problem then. You know one wrong use case, and you refuse to admit that there are other legitimate ones.

Edit: remove a few unnecessary sentences.

Edit: some people don't like Javascript crypto so much that they downvote me without saying anything.


> More challenging, yes. Riskier, no.

Please explain. Is it that it is more challenging, but in a way that it's not more difficult to get it right (what exactly is the challenge then?) or is it not riskier because the higher probability of getting it wrong does not decrease the probability of getting it right (how exactly do you increase one probability without decreasing the probability of the negated case?)?

> This applies not only to Javascript, but also to all scripting languages.

So, a bridge built from matches isn't any more robust than a bridge built from toothpicks, therefore building bridges from toothpicks is a good idea (nevermind that other people are using reinforced concrete for bridge construction)? I'm sorry, but I can't quite follow your argument.

> If you disagree, you're invited to take a look at End-To-End, find a side-channel leak and write an exploit for it. You could earn serious cold cash with that finding.

You are not seriously bringing forward the "secure-because-hacking-contest" argument, are you?

> Re your last point: if doing SSH in a browser isn't crypto I don't know what could be.

Sure it is, but it still is rather obviously not what those posts are primarily attacking. Or maybe it is, if anyone claims or implies that this "SSH-client in a browser" is any more secure than "browser frontend to SSH-client on the server". Which I think is kinda the whole reason for its existence? Performance- and complexity-wise, I doubt that it makes any sense at all to implement the SSH protocol itself in the browser in that case, vs. using a native SSH client on the server.


> If you disagree, you're invited to take a look at End-To-End, find a side-channel leak and write an exploit for it. You could earn serious cold cash with that finding.

For one thing, the IDEA implementation seems to be incorrect. In IDEA, multiplication is defined as multiplication modulo 2^16 + 1, where 0 means 2^16 [3]. However, looking at the multiplication function:

https://code.google.com/p/end-to-end/source/browse/javascrip...

When x == 0 but y != 0, the result of the modular multiplication is always 0, when it should not be. The correct code would be (in glorious C syntax, everything unsigned and 32-bit):

    if(x != 0) {
        if(y != 0) {
            return x*y % 65537; // result fits in 32 bits
        }
        else return 65537 - x; // or 1 - x mod 2^16
    } else return 65537 - y; // or 1 - y mod 2^16
Of course, even if correct this code is still vulnerable to timing attacks (under contrived conditions) [1]. This can be worked around using a little bitwise magic:

    t0  = 65537 - x;
    t1  = 65537 - y;
    t2  = x*y % 65537;
    b0  = -(1 ^ ((x | -x) >> 31)); // 0xfff..ff if x == 0
    b1  = -(1 ^ ((y | -y) >> 31)); // 0xfff..ff if y == 0
    return ((t0&~b0&b1) | (t1&b0&~b1) | (t2&~b0&~b1) | (1&b0&b1))&0xFFFF;
Additionally, the modular inversion seems to be needlessly complicated by using Euclid's algorithm (and I'm not sure it's correct either: it seems not to respect the "0 means 2^16" rule). Use the usual a^(p-2) mod p inversion trick, using an optimal addition chain [2], to make it simpler, constant-time, and possibly faster.

None of this is Javascript's fault, for what it's worth. But I certainly don't expect Javascript to make it any easier to write correct code, much by the contrary.

EDIT: Fixed constant-time code.

[1] https://www.schneier.com/paper-side-channel2.pdf

[2] http://wwwhomes.uni-bielefeld.de/cgi-bin/cgiwrap/achim/scrip...

[3] http://www.isiweb.ee.ethz.ch/papers/arch/xlai-mass-inspec-19...


Thanks for the report. I'll take a look and get back to you. Where can I contact you?

Edit: I've just filed https://code.google.com/p/end-to-end/issues/detail?id=82. We can discuss the problems of IDEA there. Thanks!


That link gives me a 403 error? In any case, I've put an email in my HN profile.


Oh yeah, it was restricted to my team. I'll make it public, and notify you via email. BTW IDEA is not enabled/registered.


This is a fantastic post that deserves to be on the front page of HN.




Disclaimer: I contribute to the core crypto library in Google End-To-End.

I was also a student of Prof. Boneh. I took his CS255, and became a TA for his infamous's Crypto I class on Coursera. So I guess at the end of the day it's still Boneh's teaching that has helped my colleagues and me create this library ;-).

SJCL is a great library, but it didn't quite work for us because:

* It isn't a Closure library. We want to use Closure because it supports types, which in turn make it easier and less error-prone to develop crypto code.

* It doesn't support typed arrays. We don't have typed arrays in End-To-End yet, but we're working on that.

* It doesn't support all the curves we want, and it seems that the main developer isn't interested in adding new curves, e.g., Curve25519.

* It doesn't have ciphers or signature schemes that we need such as RSA, Ed25519, deterministic ECDSA, etc.


Have you guys took a look at https://github.com/indutny/elliptic ?


Oh we haven't. Looks like it's a nice library. One question: it seems that you use the message directly, instead of its hash, in ECDSA? [1].

[1] https://github.com/indutny/elliptic/blob/master/lib/elliptic...

PS: were you the guy that won the CloudFlare's HeartBleed challenge? great work :-).


I do expect users to hash the message before passing it to ECDSA, this way you could use any hashing library with it. Though, elliptic.js does actually depends on hash.js to seed it's PRNG.

Thank you!


> I do expect users to hash the message before passing it to ECDSA, this way you could use any hashing library with it. Though, elliptic.js does actually depends on hash.js to seed it's PRNG.

I think this isn't a good design because most people won't know that they must hash the message before passing it to the ECDSA. People will misuse it, and open themselves to attacks.

What you can do instead is to pick the right hash based on the curve, like what we did in End-To-End: https://code.google.com/p/end-to-end/source/browse/javascrip....


Anyway, it would be interesting to compare speeds of our implementations. I'm really obsessed with try to reach 1ms verification, but so far only got to 4ms.


I actually already have a hash in `elliptic.curves` presets, but thanks for the idea!


Hello,

maybe a stupid question, but any reason why not use OpenPGP.js?

Is it even worse for your case than SJCL?


Not a stupid question at all. We actually considered this option, but OpenPGP.js looked pretty bad back then.

Security-wise the library wasn't in good shape. One of our cryptographers would "classify [OpenPGP.js] as trash". It has been audited recently, but the result doesn't look very good either [1]. I don't know the current status though.

OpenPGP.js didn't actually implement most of the ciphers - it just imported them from various sources. This made the library inconsistent, i.e., some functions expect string, while others expect byte array, which in turn made it harder to use correctly in a language like Javascript. If we chose OpenPGP.js, we needed to change these ciphers anyway, so we thought it's just better to write them from scratch.

[1] https://cure53.de/pentest-report_openpgpjs.pdf.


I'm a contributor to OpenPGP.js. I understand your choice as the code was indeed in quite bad shape several months ago. I do want to point out though, that the code has gone through a big refactoring an cleanup since then: https://github.com/openpgpjs/openpgpjs/releases

We also fixed all critical, high and medium issue: https://github.com/openpgpjs/openpgpjs/wiki/Cure53-security-...

Having said that, a consistent rewrite using typed array and native web crypto apis under the hood does indeed sound very reasonable. I saw that native web crypto is not used throughout. What are your plans in regards to web crypto?

Also what is the predicted timeline for getting End-to-End into a production ready state? We would be quite interested in using it as a standalone library in our Chrome Packaged App: https://whiteout.io

Thanks


Thanks for the update on OpenPGP.js.

> What are your plans in regards to web crypto?

The plan is to use WebCrypto if it's available. We've moved RSA to WebCrypto, and the next targets are ECDH and ECDSA.

> Also what is the predicted timeline for getting End-to-End into a production ready state? We would be quite interested in using it as a standalone library in our Chrome Packaged App: https://whiteout.io

I can't tell you about our timeline for the extension. But if you just want to use the crypto library, you may want to wait for a couple of weeks, just to make sure none discovers any serious vulnerabilities.

I like WhiteOut. It's a great product in the right direction. We really want and will support the usage of the library in products like yours.


Thanks for for reply. I'm wondering if you know if it's possible to use the AES-CFB mode from the Web Crypto Apis, since the OpenPGP CFB (resync) mode seems to have special requirements?

> I like WhiteOut. It's a great product in the right direction. We really want and will support the usage of the library in products like yours.

Thanks! Is there a guide somewhere that explains how to build the standalone lib?


> Thanks for for reply. I'm wondering if you know if it's possible to use the AES-CFB mode from the Web Crypto Apis, since the OpenPGP CFB (resync) mode seems to have special requirements?

I haven't looked into it.

> Thanks! Is there a guide somewhere that explains how to build the standalone lib?

No, there isn't. But can you file a bug with us? I'll make sure we have something for you.

PS: how can I contact you?


My email is tankred@whiteout.io


IIRC, openpgp.js is what both Lavaboom and Protonmail use.


Thanks.

I considered using OpenPGP.js in one project, I didn't go so deep though. Thanks for the information.


In the long term, could you extract the underlying crypto library and make it available for others to use in easy form? Crypto.js is pretty difficult to use and I keep seeing people including the files into their projects because of this. I'm mainly looking for:

* Officially hosted on GitHub (or at least official mirror)

* Bower and NPM packet management

* Common.js modules for Node


Yes. This is something we or at least I would do in a few months.


> his infamous's Crypto I class

s/infamous/famous.


> We know the NSA has found weaknesses in certain implementations of elliptic-curve based cryptography in the past

No, we don't.

Even djb wants people to use ECC. Note that End-To-End supports not only NIST's curves but also djb's.


The extension encrypts and saves the drafts in localStorage.


I wrote this blog.

I found the mistakes in other people's code, so I didn't complain for myself.


Ha. This is probably something that we mountain view folks would enjoy working on :-).

I've updated my blog on how to recover the private key from the CRT parameters stored in the private key: http://vnhacker.blogspot.com/2014/04/idea-to-solve-cloudflar.... Trivial math, but still interesting to see how it actually works.


I wrote a tool some time ago. It's 10 lines of Python using pyasn1.



Very interesting. So, just with the private key given p/q and the modulus is really possible to extract the private key? I saw the RSATool (https://github.com/ius/rsatool), but it needs an "n" and "d" parameter. So, how to use the output from this modified hertbeet exploit with RSATool since it only prints "Using Modulus", "Got result:" and "Found Prime" and all are much larger in comparison with parameters for RSATOOL. Thanks.


If you have modulus n and prime p, you can get the other prime q by dividing n by p. This gives you both primes, which is the input to RSA key generation (along with the public exponent which is usually 65537, but can be extracted from the X.509 certificate along with the modulus).


apparently these temp values are scrubbed by openssl. i would definitely verify because there could be some implementation bug that stops their scrubbing. so what nginx does is:

  handle_request:
    do_decryption
    scrub_temporaries
    write_to_client
  handle_another_request:
    ..
because nginx is single threaded there shouldn't be any requests handled between do_decryption and scrub_temporaries. but this is a problem on other servers.

  static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
               unsigned char *to, RSA *rsa, int padding)
          {
        ...

        if (ctx != NULL)
                {
                BN_CTX_end(ctx);
                BN_CTX_free(ctx);
                }
        if (buf != NULL)
                {
                OPENSSL_cleanse(buf,num);
                OPENSSL_free(buf);
                }
        return(r);


  void BN_CTX_free(BN_CTX *ctx)
        {
        if (ctx == NULL)
                return;
  #ifdef BN_CTX_DEBUG
        {
        BN_POOL_ITEM *pool = ctx->pool.head;
        fprintf(stderr,"BN_CTX_free, stack-size=%d, pool-bignums=%d\n",
                ctx->stack.size, ctx->pool.size);
        fprintf(stderr,"dmaxs: ");
        while(pool) {
                unsigned loop = 0;
                while(loop < BN_CTX_POOL_SIZE)
                        fprintf(stderr,"%02x ", pool->vals[loop++].dmax);
                pool = pool->next;
        }
        fprintf(stderr,"\n");
        }
  #endif
        BN_STACK_finish(&ctx->stack);
        BN_POOL_finish(&ctx->pool);
        OPENSSL_free(ctx);
        }


  static void BN_POOL_finish(BN_POOL *p)
          {
          while(p->head)
                  {
                  unsigned int loop = 0;
                  BIGNUM *bn = p->head->vals;
                  while(loop++ < BN_CTX_POOL_SIZE)
                          {
                          if(bn->d) BN_clear_free(bn);
                          bn++;
                          }
                  p->current = p->head->next;
                  OPENSSL_free(p->head);
                  p->head = p->current;
                  }
          }


  void BN_clear_free(BIGNUM *a)
          {
          int i;

          if (a == NULL) return;
          bn_check_top(a);
          if (a->d != NULL)
                  {
                  OPENSSL_cleanse(a->d,a->dmax*sizeof(a->d[0]));
                  if (!(BN_get_flags(a,BN_FLG_STATIC_DATA)))
                          OPENSSL_free(a->d);
                  }
          i=BN_get_flags(a,BN_FLG_MALLOCED);
          OPENSSL_cleanse(a,sizeof(BIGNUM));
          if (i)
                  OPENSSL_free(a);
          }

  void OPENSSL_cleanse(void *ptr, size_t len)
          {
          unsigned char *p = ptr;
          size_t loop = len, ctr = cleanse_ctr;
          while(loop--)
                  {
                  *(p++) = (unsigned char)ctr;
                  ctr += (17 + ((size_t)p & 0xF));
                  }
          p=memchr(ptr, (unsigned char)ctr, len);
          if(p)
                  ctr += (63 + (size_t)p);
          cleanse_ctr = (unsigned char)ctr;
          }


Yeah, you're correct. So it seems that you don't need math to solve this challenge, but maybe luck and patience.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: