digitalbazaar / forge

A native implementation of TLS in Javascript and tools to write crypto-based and network-heavy webapps

Home Page:https://digitalbazaar.com/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ed25519 signature verify does not reject changed message

dongryphon opened this issue · comments

Am I doing something wrong? I seem to always get true from verify even if the message is not the original message:

Test case:

        var pwd = 'password';
        var msg = 'I have something to say';

        var md = SHA256.create();
        md.update(pwd, 'utf8');
        var seed = md.digest().getBytes();
        var kp = ED25519.generateKeyPair({seed: seed});

        md = SHA256.create();
        md.update(msg, 'utf8');

        var signature = ED25519.sign({
            md: md,
            privateKey: kp.privateKey
        });

        md = SHA256.create();
        md.update(msg + '!', 'utf8');  // different msg

        var verified = ED25519.verify({
          md: md,
          signature: signature,
          publicKey: kp.publicKey
        });

        ASSERT.equal(verified, false);  // << FAIL

Could it be because ED25519.generateKeyPair seems to produce the same public key?

        let pwd = 'password';

        let md = SHA256.create();
        md.update(pwd, 'utf8');
        let seed = md.digest().getBytes();
        let kp = ED25519.generateKeyPair({seed: seed});

        md = SHA256.create();
        md.update(pwd + '!', 'utf8');
        let seed2 = md.digest().getBytes();
        let kp2 = ED25519.generateKeyPair({ seed: seed2 });

        expect(seed).not.toEqual(seed2);
        expect(kp.privateKey).not.toEqual(kp2.privateKey);
        expect(kp.publicKey).not.toEqual(kp2.publicKey);   // << FAIL

I suspect (even if related) this is a different issue - see #1035

To answer one question it is not verifying just any message, there is a unit test for a basic fail case:

it('should fail to verify a signature', function() {
      var pwd = 'password';
      var md = SHA256.create();
      md.update(pwd, 'utf8');
      var seed = md.digest().getBytes();
      var kp = ED25519.generateKeyPair({seed: seed});

      var signature = db64(b64BadSignature);

      var verified = ED25519.verify({
        message: 'test',
        encoding: 'utf8',
        signature: signature,
        publicKey: kp.publicKey
      });
      ASSERT.equal(verified, false);
    });

I believe the issue is that the passed in message digest is longer and contains the original signature. Have you tried an md that's the same length but different or an md that is one character less than the original? My apologies about not testing this myself. Will try to add tests for it asap.

Thanks for the reply... so the md (sha256) is always the same length. Not sure I follow what that has to do with the signature length. Been a long time since I've done DSA so I (naively) expected verify to reject any but the original message/md

Thanks for the reply... so the md (sha256) is always the same length. Not sure I follow what that has to do with the signature length. Been a long time since I've done DSA so I (naively) expected verify to reject any but the original message/md

You have a good point here. Could you add this as a test to the ed25519 unit tests?

I doubt I'll have a chance to do a PR to the repo right away. I am using the package via npm at present and noticed odd things in testing my code. I semi-reformulated my tests to look like those in the repo but you can tell I am using a different test fw (expect vs ASSERT etc)

I'm going to close this issue since it is the same as #1035