Skip to content
This repository has been archived by the owner on Feb 12, 2022. It is now read-only.

VXEDDSA compliance with libsodium keys? #90

Closed
c-geek opened this issue Oct 16, 2017 · 2 comments
Closed

VXEDDSA compliance with libsodium keys? #90

c-geek opened this issue Oct 16, 2017 · 2 comments

Comments

@c-geek
Copy link

c-geek commented Oct 16, 2017

Hello,

I'm trying to use VXEDDSA functions from existing Ed25519 keys, generated by Scrypt.

I've tried to take an example from test test_unique_signatures which was working as expected, and changed the public/private keys with the ones I get. But I finally got:

05:f7:d6:8d:a9:19:33:1a:9b:d5:2a:4f:f8:1c:8c:74:0e:6f:76:63:52:24:89:5d:4c:37:1e:68:d5:c7:f3:10:32
c8:df:2f:9e:7f:0c:e8:83:33:cd:6e:f7:3c:5b:bc:dc:75:46:a1:65:fc:5a:62:f6:ba:24:e4:89:03:29:1d:b0
54:68:69:73:20:69:73:20:75:6e:69:71:75:65:2e
45:dc:7b:81:6b:01:b3:6c:fa:16:45:dc:ae:8a:c9:bc:8e:52:3c:d8:6d:00:7d:19:95:3f:03:e7:d5:45:54:a0
curve_decode_point: 0
curve_decode_private_point: 0
curve_calculate_vrf_signature: 0
curve_verify_vrf_signature: -1011

Is this key generated by Scrypt supposed to work with libsignal VXEDDSA functions?

I do not master the crypto functions very well, so I need your help. A hint would be enough, I need to know which path to follow.

#include <math.h>
#include <printf.h>
#include <memory.h>
#include "../src/signal_protocol.h"
#include "../src/signal_protocol_internal.h"
#include "randombytes/randombytes.h"
#include <iostream>

#include <openssl/opensslv.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>
#include <openssl/sha.h>
#include <stdbool.h>

signal_context *global_context;

static void hex_dump(const uint8_t *data, size_t size)
{
  for (size_t i = 0; i < size; i++) {
    bool last = i + 1 == size;
    printf("%02x%c", (unsigned int)data[i], last ? '\n' : ':');
  }
}

int test_random_generator(uint8_t *data, size_t len, void *user_data)
{
  if(randombytes(data, len)) {
    return 0;
  }
  else {
    return SG_ERR_UNKNOWN;
  }
}

int main(int argc, char **argv) {

  int result;
  result = signal_context_create(&global_context, 0);

  global_context->crypto_provider.random_func = test_random_generator;


  size_t i;
  size_t r;

  uint8_t publicKey[] = {
      0x05,
      0xf7, 0xd6, 0x8d, 0xa9, 0x19, 0x33, 0x1a, 0x9b,
      0xd5, 0x2a, 0x4f, 0xf8, 0x1c, 0x8c, 0x74, 0x0e,
      0x6f, 0x76, 0x63, 0x52, 0x24, 0x89, 0x5d, 0x4c,
      0x37, 0x1e, 0x68, 0xd5, 0xc7, 0xf3, 0x10, 0x32};
  uint8_t privateKey[] = {
      0xc8, 0xdf, 0x2f, 0x9e, 0x7f, 0x0c, 0xe8, 0x83,
      0x33, 0xcd, 0x6e, 0xf7, 0x3c, 0x5b, 0xbc, 0xdc,
      0x75, 0x46, 0xa1, 0x65, 0xfc, 0x5a, 0x62, 0xf6,
      0xba, 0x24, 0xe4, 0x89, 0x03, 0x29, 0x1d, 0xb0};
  uint8_t message[] = {
      0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
      0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x2e};
  uint8_t vrf[] = {
      0x45, 0xDC, 0x7B, 0x81, 0x6B, 0x01, 0xB3, 0x6C,
      0xFA, 0x16, 0x45, 0xDC, 0xAE, 0x8A, 0xC9, 0xBC,
      0x8E, 0x52, 0x3C, 0xD8, 0x6D, 0x00, 0x7D, 0x19,
      0x95, 0x3F, 0x03, 0xE7, 0xD5, 0x45, 0x54, 0xA0
  };

  hex_dump(publicKey, sizeof(publicKey));
  hex_dump(privateKey, sizeof(privateKey));
  hex_dump(message, sizeof(message));
  hex_dump(vrf, sizeof(vrf));

//  int result;
  ec_public_key *public_key = 0;
  ec_private_key *private_key = 0;
  signal_buffer *signature = 0;
  signal_buffer *vrf_output = 0;

  result = curve_decode_point(&public_key, publicKey, sizeof(publicKey), global_context);
  printf("curve_decode_point: %d\n", result);

  result = curve_decode_private_point(&private_key, privateKey, sizeof(privateKey), global_context);
  printf("curve_decode_private_point: %d\n", result);

  result = curve_calculate_vrf_signature(global_context, &signature,
                                         private_key, message, sizeof(message));
  printf("curve_calculate_vrf_signature: %d\n", result);


//  message[r % 2] ^= 0x01;

  result = curve_verify_vrf_signature(global_context, &vrf_output,
                                      public_key, message, sizeof(message),
                                      signal_buffer_data(signature), signal_buffer_len(signature));
  printf("curve_verify_vrf_signature: %d\n", result);

  printf("signal_buffer_len(vrf_output): %d\n", signal_buffer_len(vrf_output));
  printf("sizeof(vrf): %d\n", sizeof(vrf));
  printf("sizeof(signature): %d\n", sizeof(signature));
  printf("signal_buffer_len(signature): %d\n", signal_buffer_len(signature));
  printf("sizeof(signature): %d\n", sizeof(signature));
  printf("memcmp(signal_buffer_data(vrf_output), vrf, sizeof(vrf)): %d\n", memcmp(signal_buffer_data(vrf_output), vrf, sizeof(vrf)));
//  ck_assert_int_eq(signal_buffer_len(vrf_output), sizeof(vrf));

  /* Cleanup */
  signal_buffer_free(signature);
  signal_buffer_free(vrf_output);
  SIGNAL_UNREF(public_key);
  SIGNAL_UNREF(private_key);

  printf("Blabla 2: %d", result);
  return 0;
}
@c-geek c-geek changed the title Compliance with libsodium keys? VXEDDSA compliance with libsodium keys? Oct 17, 2017
@c-geek
Copy link
Author

c-geek commented Oct 17, 2017

Also I've tested this keyring with simple XEDDSA functions and it works very well:

  • curve_calculate_signature
  • curve_verify_signature

So it's really a problem when using VXEDDSA functions.

Also, I tried TweetNacl random keypairs but I get the same result: working with XEDDSA, invalid signature for VXEDDSA.

😕

@c-geek
Copy link
Author

c-geek commented Oct 17, 2017

OK so it appears that the VXEDDSA compliant keys generated by libsignal-protocol-c are valid because of this code, occuring just after the random bytes gathering:

key->data[0] &= 248;
key->data[31] &= 127;
key->data[31] |= 64;

This is apparenlty known as "clamping". The problem is: if I apply such clamping to my seeds, the initial pubkey won't match signatures made by a clamped seed (= clamped private key).

@c-geek c-geek closed this as completed Oct 17, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

No branches or pull requests

1 participant