x25519 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES.md +7 -0
- data/Rakefile +4 -2
- data/ext/{x25519 → x25519_precomputed}/cputest.c +0 -0
- data/ext/x25519_precomputed/extconf.rb +9 -0
- data/ext/{x25519/rfc7748_precomputed → x25519_precomputed}/fp25519_x64.c +0 -0
- data/ext/{x25519/rfc7748_precomputed → x25519_precomputed}/fp25519_x64.h +0 -0
- data/ext/{x25519/rfc7748_precomputed → x25519_precomputed}/table_ladder_x25519.h +0 -0
- data/ext/x25519_precomputed/x25519_precomputed.c +86 -0
- data/ext/{x25519/rfc7748_precomputed/rfc7748_precomputed.h → x25519_precomputed/x25519_precomputed.h} +4 -0
- data/ext/{x25519/rfc7748_precomputed → x25519_precomputed}/x25519_x64.c +3 -3
- data/ext/{x25519/ref10 → x25519_ref10}/api.h +0 -0
- data/ext/{x25519/ref10 → x25519_ref10}/base.c +1 -4
- data/ext/x25519_ref10/extconf.rb +9 -0
- data/ext/{x25519/ref10 → x25519_ref10}/fe.h +0 -0
- data/ext/{x25519/ref10 → x25519_ref10}/fe_0.c +0 -0
- data/ext/{x25519/ref10 → x25519_ref10}/fe_1.c +0 -0
- data/ext/{x25519/ref10 → x25519_ref10}/fe_add.c +0 -0
- data/ext/{x25519/ref10 → x25519_ref10}/fe_copy.c +0 -0
- data/ext/{x25519/ref10 → x25519_ref10}/fe_cswap.c +0 -0
- data/ext/{x25519/ref10 → x25519_ref10}/fe_frombytes.c +0 -0
- data/ext/{x25519/ref10 → x25519_ref10}/fe_invert.c +0 -0
- data/ext/{x25519/ref10 → x25519_ref10}/fe_mul.c +0 -0
- data/ext/{x25519/ref10 → x25519_ref10}/fe_mul121666.c +0 -0
- data/ext/{x25519/ref10 → x25519_ref10}/fe_sq.c +0 -0
- data/ext/{x25519/ref10 → x25519_ref10}/fe_sub.c +0 -0
- data/ext/{x25519/ref10 → x25519_ref10}/fe_tobytes.c +0 -0
- data/ext/{x25519/ref10 → x25519_ref10}/montgomery.h +0 -0
- data/ext/{x25519/ref10 → x25519_ref10}/pow225521.h +0 -0
- data/ext/{x25519/ref10 → x25519_ref10}/scalarmult.c +1 -0
- data/ext/x25519_ref10/x25519_ref10.c +80 -0
- data/ext/x25519_ref10/x25519_ref10.h +15 -0
- data/lib/x25519.rb +54 -0
- data/lib/x25519/montgomery_u.rb +29 -0
- data/lib/x25519/scalar.rb +56 -0
- data/lib/x25519/version.rb +5 -0
- data/x25519.gemspec +7 -3
- metadata +38 -31
- data/ext/x25519/extconf.rb +0 -31
- data/ext/x25519/x25519.c +0 -325
- data/ext/x25519/x25519.h +0 -24
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 25356788bb752f943f14d47eb09477c80e8831f3
|
|
4
|
+
data.tar.gz: c90ad445482d6d376bb957187ba1c01a4ade1c7d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e16c1bfd49e7dd844676159714e6145d357259002800a1033b7993c7ac4049e238dba7c5b8aa1bdff12dced90dfc5a5e70caaf054a3f401eed6efdcd9da7d12f
|
|
7
|
+
data.tar.gz: 173e2fecb31f6b0bc09287fe9d7b7bba563e2cac1ca8b9877290b86241cd7cbbb0b4c8d20f212c2dfd777327a50ef6ac403966f9babac4ced0c38fddc4bfba60
|
data/CHANGES.md
CHANGED
data/Rakefile
CHANGED
|
@@ -6,8 +6,10 @@ require "rake/clean"
|
|
|
6
6
|
CLEAN.include("**/*.o", "**/*.so", "**/*.bundle", "pkg", "tmp")
|
|
7
7
|
|
|
8
8
|
require "rake/extensiontask"
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
%w[precomputed ref10].each do |provider|
|
|
10
|
+
Rake::ExtensionTask.new("x25519_#{provider}") do |ext|
|
|
11
|
+
ext.ext_dir = "ext/x25519_#{provider}"
|
|
12
|
+
end
|
|
11
13
|
end
|
|
12
14
|
|
|
13
15
|
require "rspec/core/rake_task"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Ruby C extension providing bindings to the rfc7748_precomputed implementation of
|
|
3
|
+
the X25519 Diffie-Hellman algorithm
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
#include "ruby.h"
|
|
7
|
+
#include "x25519_precomputed.h"
|
|
8
|
+
|
|
9
|
+
static VALUE mX25519 = Qnil;
|
|
10
|
+
static VALUE mX25519_Precomputed = Qnil;
|
|
11
|
+
|
|
12
|
+
static VALUE mX25519_Scalar_multiply(VALUE self, VALUE scalar, VALUE montgomery_u);
|
|
13
|
+
static VALUE mX25519_Scalar_multiply_base(VALUE self, VALUE scalar);
|
|
14
|
+
static VALUE mX25519_is_available(VALUE self);
|
|
15
|
+
|
|
16
|
+
/* Initialize the x25519_precomputed C extension */
|
|
17
|
+
void Init_x25519_precomputed()
|
|
18
|
+
{
|
|
19
|
+
mX25519 = rb_define_module("X25519");
|
|
20
|
+
mX25519_Precomputed = rb_define_module_under(mX25519, "Precomputed");
|
|
21
|
+
|
|
22
|
+
rb_define_singleton_method(mX25519_Precomputed, "multiply", mX25519_Scalar_multiply, 2);
|
|
23
|
+
rb_define_singleton_method(mX25519_Precomputed, "multiply_base", mX25519_Scalar_multiply_base, 1);
|
|
24
|
+
rb_define_singleton_method(mX25519_Precomputed, "available?", mX25519_is_available, 0);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* Variable-base scalar multiplication */
|
|
28
|
+
static VALUE mX25519_Scalar_multiply(VALUE self, VALUE scalar, VALUE montgomery_u)
|
|
29
|
+
{
|
|
30
|
+
/* X25519_KEY ensures inputs are aligned at 32-bytes */
|
|
31
|
+
X25519_KEY raw_scalar, raw_montgomery_u, product;
|
|
32
|
+
|
|
33
|
+
StringValue(scalar);
|
|
34
|
+
if(RSTRING_LEN(scalar) != X25519_KEYSIZE_BYTES) {
|
|
35
|
+
rb_raise(
|
|
36
|
+
rb_eArgError,
|
|
37
|
+
"expected %d-byte scalar, got %ld",
|
|
38
|
+
X25519_KEYSIZE_BYTES,
|
|
39
|
+
RSTRING_LEN(scalar)
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
StringValue(montgomery_u);
|
|
44
|
+
if(RSTRING_LEN(montgomery_u) != X25519_KEYSIZE_BYTES) {
|
|
45
|
+
rb_raise(
|
|
46
|
+
rb_eArgError,
|
|
47
|
+
"expected %d-byte Montgomery-u coordinate, got %ld",
|
|
48
|
+
X25519_KEYSIZE_BYTES,
|
|
49
|
+
RSTRING_LEN(montgomery_u)
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
memcpy(raw_scalar, RSTRING_PTR(scalar), X25519_KEYSIZE_BYTES);
|
|
54
|
+
memcpy(raw_montgomery_u, RSTRING_PTR(montgomery_u), X25519_KEYSIZE_BYTES);
|
|
55
|
+
x25519_precomputed_scalarmult(product, raw_scalar, raw_montgomery_u);
|
|
56
|
+
|
|
57
|
+
return rb_str_new((const char *)product, X25519_KEYSIZE_BYTES);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* Fixed-base scalar multiplication */
|
|
61
|
+
static VALUE mX25519_Scalar_multiply_base(VALUE self, VALUE scalar)
|
|
62
|
+
{
|
|
63
|
+
/* X25519_KEY ensures inputs are aligned at 32-bytes */
|
|
64
|
+
X25519_KEY raw_scalar, product;
|
|
65
|
+
|
|
66
|
+
StringValue(scalar);
|
|
67
|
+
if(RSTRING_LEN(scalar) != X25519_KEYSIZE_BYTES) {
|
|
68
|
+
rb_raise(
|
|
69
|
+
rb_eArgError,
|
|
70
|
+
"expected %d-byte scalar, got %ld",
|
|
71
|
+
X25519_KEYSIZE_BYTES,
|
|
72
|
+
RSTRING_LEN(scalar)
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
memcpy(raw_scalar, RSTRING_PTR(scalar), X25519_KEYSIZE_BYTES);
|
|
77
|
+
x25519_precomputed_scalarmult_base(product, raw_scalar);
|
|
78
|
+
|
|
79
|
+
return rb_str_new((const char *)product, X25519_KEYSIZE_BYTES);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* Is the x25519_precomputed backend supported on this CPU? */
|
|
83
|
+
static VALUE mX25519_is_available(VALUE self)
|
|
84
|
+
{
|
|
85
|
+
return check_4th_gen_intel_core_features() ? Qtrue : Qfalse;
|
|
86
|
+
}
|
|
@@ -30,4 +30,8 @@
|
|
|
30
30
|
#define X25519_KEYSIZE_BYTES 32
|
|
31
31
|
typedef ALIGN uint8_t X25519_KEY[X25519_KEYSIZE_BYTES];
|
|
32
32
|
|
|
33
|
+
void x25519_precomputed_scalarmult(uint8_t *shared, uint8_t *private_key, uint8_t *session_key);
|
|
34
|
+
void x25519_precomputed_scalarmult_base(uint8_t *session_key, uint8_t *private_key);
|
|
35
|
+
int check_4th_gen_intel_core_features();
|
|
36
|
+
|
|
33
37
|
#endif /* RFC7748_PRECOMPUTED_H */
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
#include "fp25519_x64.h"
|
|
19
19
|
#include "table_ladder_x25519.h"
|
|
20
|
-
#include "
|
|
20
|
+
#include "x25519_precomputed.h"
|
|
21
21
|
|
|
22
22
|
/****** Implementation of Montgomery Ladder Algorithm ************/
|
|
23
23
|
static inline void cswap_x64(uint64_t bit, uint64_t *const px, uint64_t *const py)
|
|
@@ -32,7 +32,7 @@ static inline void cswap_x64(uint64_t bit, uint64_t *const px, uint64_t *const p
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
void
|
|
35
|
+
void x25519_precomputed_scalarmult(uint8_t *shared, uint8_t *private_key, uint8_t *session_key)
|
|
36
36
|
{
|
|
37
37
|
ALIGN uint64_t buffer[4*NUM_WORDS_ELTFP25519_X64];
|
|
38
38
|
ALIGN uint64_t coordinates[4*NUM_WORDS_ELTFP25519_X64];
|
|
@@ -133,7 +133,7 @@ void x25519_rfc7748_precomputed_scalarmult(uint8_t *shared, uint8_t *private_key
|
|
|
133
133
|
private_key[0] = (uint8_t)(save & 0xFF);
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
void
|
|
136
|
+
void x25519_precomputed_scalarmult_base(uint8_t *session_key, uint8_t *private_key)
|
|
137
137
|
{
|
|
138
138
|
ALIGN uint64_t buffer[4*NUM_WORDS_ELTFP25519_X64];
|
|
139
139
|
ALIGN uint64_t coordinates[4*NUM_WORDS_ELTFP25519_X64];
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Ruby C extension providing bindings to the ref10 implementation of the
|
|
3
|
+
X25519 Diffie-Hellman algorithm
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
#include "ruby.h"
|
|
7
|
+
#include "x25519_ref10.h"
|
|
8
|
+
|
|
9
|
+
static VALUE mX25519 = Qnil;
|
|
10
|
+
static VALUE mX25519_Ref10 = Qnil;
|
|
11
|
+
|
|
12
|
+
static VALUE mX25519_Scalar_multiply(VALUE self, VALUE scalar, VALUE montgomery_u);
|
|
13
|
+
static VALUE mX25519_Scalar_multiply_base(VALUE self, VALUE scalar);
|
|
14
|
+
|
|
15
|
+
/* Initialize the x25519_ref10 C extension */
|
|
16
|
+
void Init_x25519_ref10()
|
|
17
|
+
{
|
|
18
|
+
mX25519 = rb_define_module("X25519");
|
|
19
|
+
mX25519_Ref10 = rb_define_module_under(mX25519, "Ref10");
|
|
20
|
+
|
|
21
|
+
rb_define_singleton_method(mX25519_Ref10, "multiply", mX25519_Scalar_multiply, 2);
|
|
22
|
+
rb_define_singleton_method(mX25519_Ref10, "multiply_base", mX25519_Scalar_multiply_base, 1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* Variable-base scalar multiplication */
|
|
26
|
+
static VALUE mX25519_Scalar_multiply(VALUE self, VALUE scalar, VALUE montgomery_u)
|
|
27
|
+
{
|
|
28
|
+
X25519_KEY product;
|
|
29
|
+
|
|
30
|
+
StringValue(scalar);
|
|
31
|
+
if(RSTRING_LEN(scalar) != X25519_KEYSIZE_BYTES) {
|
|
32
|
+
rb_raise(
|
|
33
|
+
rb_eArgError,
|
|
34
|
+
"expected %d-byte scalar, got %ld",
|
|
35
|
+
X25519_KEYSIZE_BYTES,
|
|
36
|
+
RSTRING_LEN(scalar)
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
StringValue(montgomery_u);
|
|
41
|
+
if(RSTRING_LEN(montgomery_u) != X25519_KEYSIZE_BYTES) {
|
|
42
|
+
rb_raise(
|
|
43
|
+
rb_eArgError,
|
|
44
|
+
"expected %d-byte Montgomery-u coordinate, got %ld",
|
|
45
|
+
X25519_KEYSIZE_BYTES,
|
|
46
|
+
RSTRING_LEN(montgomery_u)
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
x25519_ref10_scalarmult(
|
|
51
|
+
product,
|
|
52
|
+
(const uint8_t *)RSTRING_PTR(scalar),
|
|
53
|
+
(const uint8_t *)RSTRING_PTR(montgomery_u)
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
return rb_str_new((const char *)product, X25519_KEYSIZE_BYTES);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* Fixed-base scalar multiplication */
|
|
60
|
+
static VALUE mX25519_Scalar_multiply_base(VALUE self, VALUE scalar)
|
|
61
|
+
{
|
|
62
|
+
X25519_KEY product;
|
|
63
|
+
|
|
64
|
+
StringValue(scalar);
|
|
65
|
+
if(RSTRING_LEN(scalar) != X25519_KEYSIZE_BYTES) {
|
|
66
|
+
rb_raise(
|
|
67
|
+
rb_eArgError,
|
|
68
|
+
"expected %d-byte scalar, got %ld",
|
|
69
|
+
X25519_KEYSIZE_BYTES,
|
|
70
|
+
RSTRING_LEN(scalar)
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
x25519_ref10_scalarmult_base(
|
|
75
|
+
product,
|
|
76
|
+
(const uint8_t *)RSTRING_PTR(scalar)
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
return rb_str_new((const char *)product, X25519_KEYSIZE_BYTES);
|
|
80
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#ifndef RFC7748_REF10_H
|
|
2
|
+
#define RFC7748_REF10_H
|
|
3
|
+
|
|
4
|
+
#include <stdint.h>
|
|
5
|
+
|
|
6
|
+
#define X25519_KEYSIZE_BYTES 32
|
|
7
|
+
typedef uint8_t X25519_KEY[X25519_KEYSIZE_BYTES];
|
|
8
|
+
|
|
9
|
+
/* Fixed-base scalar multiplication */
|
|
10
|
+
int x25519_ref10_scalarmult(uint8_t *q, const uint8_t *n, const uint8_t *p);
|
|
11
|
+
|
|
12
|
+
/* Variable-base scalar multiplication */
|
|
13
|
+
int x25519_ref10_scalarmult_base(uint8_t *q, const uint8_t *n);
|
|
14
|
+
|
|
15
|
+
#endif /* RFC7748_REF10_H */
|
data/lib/x25519.rb
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "securerandom"
|
|
4
|
+
|
|
5
|
+
require "x25519/version"
|
|
6
|
+
|
|
7
|
+
require "x25519/montgomery_u"
|
|
8
|
+
require "x25519/scalar"
|
|
9
|
+
|
|
10
|
+
# Native extension backends
|
|
11
|
+
require "x25519_ref10"
|
|
12
|
+
require "x25519_precomputed"
|
|
13
|
+
|
|
14
|
+
# The X25519 elliptic curve Diffie-Hellman algorithm
|
|
15
|
+
module X25519
|
|
16
|
+
module_function
|
|
17
|
+
|
|
18
|
+
# Size of an X25519 key (public or private) in bytes
|
|
19
|
+
KEY_SIZE = 32
|
|
20
|
+
|
|
21
|
+
# X25519::Precomputed requires a 4th generation Intel Core CPU or newer,
|
|
22
|
+
# so only enable it if we detect we're on a supported platform. Otherwise,
|
|
23
|
+
# fall back to the ref10 portable C implementation.
|
|
24
|
+
@provider = if X25519::Precomputed.available?
|
|
25
|
+
X25519::Precomputed
|
|
26
|
+
else
|
|
27
|
+
X25519::Ref10
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Selected provider based on the logic above
|
|
31
|
+
def provider
|
|
32
|
+
@provider
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Raw Diffie-Hellman function that acts directly on bytestrings. An
|
|
36
|
+
# alternative to the object-oriented API
|
|
37
|
+
#
|
|
38
|
+
# @param scalar_bytes [String] a serialized private scalar
|
|
39
|
+
# @param montgomery_u_bytes [String] a point we wish to multiply by the scalar
|
|
40
|
+
#
|
|
41
|
+
# @return [String] resulting point, serialized as bytes
|
|
42
|
+
def diffie_hellman(scalar_bytes, montgomery_u_bytes)
|
|
43
|
+
validate_key_bytes(scalar_bytes)
|
|
44
|
+
validate_key_bytes(montgomery_u_bytes)
|
|
45
|
+
X25519.provider.multiply(scalar_bytes, montgomery_u_bytes)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Ensure a serialized key meets the requirements
|
|
49
|
+
def validate_key_bytes(key_bytes)
|
|
50
|
+
raise TypeError, "expected String, got #{key_bytes.class}" unless key_bytes.is_a?(String)
|
|
51
|
+
return true if key_bytes.bytesize == KEY_SIZE
|
|
52
|
+
raise ArgumentError, "expected #{KEY_SIZE}-byte String, got #{key_bytes.bytesize}"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module X25519
|
|
4
|
+
# X25519 public keys and shared secrets
|
|
5
|
+
#
|
|
6
|
+
# Montgomery-u coordinates of points on the elliptic curve used by X25519
|
|
7
|
+
# (a.k.a. Curve25519)
|
|
8
|
+
class MontgomeryU
|
|
9
|
+
# Create an object representing a Montgomery-u coordinate from a bytestring
|
|
10
|
+
#
|
|
11
|
+
# @param bytes [String] 32-byte compressed Montgomery-u coordinate
|
|
12
|
+
def initialize(bytes)
|
|
13
|
+
X25519.validate_key_bytes(bytes)
|
|
14
|
+
@bytes = bytes
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Return a compressed Montgomery-u coordinate serialized as a bytestring
|
|
18
|
+
#
|
|
19
|
+
# @return [String] bytestring serialization of a Montgomery-u coordinate
|
|
20
|
+
def to_bytes
|
|
21
|
+
@bytes
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Show hex representation of serialized coordinate in string inspection
|
|
25
|
+
def inspect
|
|
26
|
+
"#<#{self.class}:#{@bytes.unpack('H*').first}>"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module X25519
|
|
4
|
+
# X25519 private keys
|
|
5
|
+
#
|
|
6
|
+
# Scalars are the integer component of scalar multiplication, multiplied
|
|
7
|
+
# against an elliptic curve point.
|
|
8
|
+
class Scalar
|
|
9
|
+
# Securely generate a random scalar
|
|
10
|
+
def self.generate
|
|
11
|
+
new(SecureRandom.random_bytes(X25519::KEY_SIZE))
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Create an X25519 scalar object from a bytestring
|
|
15
|
+
#
|
|
16
|
+
# @param bytes [String] 32-byte random secret scalar
|
|
17
|
+
def initialize(bytes)
|
|
18
|
+
X25519.validate_key_bytes(bytes)
|
|
19
|
+
@bytes = bytes
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Variable-base scalar multiplication a.k.a. Diffie-Hellman
|
|
23
|
+
#
|
|
24
|
+
# This can be used to obtain a shared secret from a public key
|
|
25
|
+
#
|
|
26
|
+
# @param montgomery_u [X25519::MontgomeryU] coordinate of the public key/point to perform D-H with
|
|
27
|
+
#
|
|
28
|
+
# @return [X25519::MontgomeryU] resulting point (i.e. D-H shared secret)
|
|
29
|
+
def multiply(montgomery_u)
|
|
30
|
+
raise TypeError, "expected X25519::MontgomeryU, got #{montgomery_u}" unless montgomery_u.is_a?(MontgomeryU)
|
|
31
|
+
MontgomeryU.new(X25519.provider.multiply(@bytes, montgomery_u.to_bytes))
|
|
32
|
+
end
|
|
33
|
+
alias diffie_hellman multiply
|
|
34
|
+
|
|
35
|
+
# Fixed-base scalar multiplication. Calculates a public key from a
|
|
36
|
+
# private scalar
|
|
37
|
+
#
|
|
38
|
+
# @return [X25519::MontgomeryU] resulting point (i.e. public key)
|
|
39
|
+
def multiply_base
|
|
40
|
+
MontgomeryU.new(X25519.provider.multiply_base(@bytes))
|
|
41
|
+
end
|
|
42
|
+
alias public_key multiply_base
|
|
43
|
+
|
|
44
|
+
# Return a bytestring representation of this scalar
|
|
45
|
+
#
|
|
46
|
+
# @return [String] scalar converted to a bytestring
|
|
47
|
+
def to_bytes
|
|
48
|
+
@bytes
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# String inspection that does not leak the private scalar
|
|
52
|
+
def inspect
|
|
53
|
+
to_s
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
data/x25519.gemspec
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
lib = File.expand_path("../lib", __FILE__)
|
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
|
+
require "x25519/version"
|
|
6
|
+
|
|
3
7
|
Gem::Specification.new do |spec|
|
|
4
8
|
spec.name = "x25519"
|
|
5
|
-
spec.version =
|
|
9
|
+
spec.version = X25519::VERSION
|
|
6
10
|
spec.authors = ["Tony Arcieri"]
|
|
7
11
|
spec.email = ["bascule@gmail.com"]
|
|
8
12
|
spec.summary = "Public key cryptography library providing the X25519 D-H function"
|
|
9
13
|
spec.description = <<-DESCRIPTION.strip.gsub(/\s+/, " ")
|
|
10
14
|
An efficient public key cryptography library for Ruby providing key
|
|
11
15
|
exchange/agreement via the X25519 (a.k.a. Curve25519) Elliptic Curve
|
|
12
|
-
Diffie-Hellman function as described in
|
|
16
|
+
Diffie-Hellman function as described in RFC 7748.
|
|
13
17
|
DESCRIPTION
|
|
14
18
|
spec.homepage = "https://github.com/cryptosphere/x25519"
|
|
15
19
|
spec.license = "MIT"
|
|
@@ -18,7 +22,7 @@ Gem::Specification.new do |spec|
|
|
|
18
22
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
19
23
|
spec.require_paths = ["lib"]
|
|
20
24
|
spec.platform = Gem::Platform::RUBY
|
|
21
|
-
spec.extensions = "ext/
|
|
25
|
+
spec.extensions = ["ext/x25519_precomputed/extconf.rb", "ext/x25519_ref10/extconf.rb"]
|
|
22
26
|
|
|
23
27
|
spec.required_ruby_version = ">= 2.2.2"
|
|
24
28
|
spec.add_development_dependency "bundler", "~> 1.16"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: x25519
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tony Arcieri
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2017-12-
|
|
11
|
+
date: 2017-12-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -26,12 +26,13 @@ dependencies:
|
|
|
26
26
|
version: '1.16'
|
|
27
27
|
description: An efficient public key cryptography library for Ruby providing key exchange/agreement
|
|
28
28
|
via the X25519 (a.k.a. Curve25519) Elliptic Curve Diffie-Hellman function as described
|
|
29
|
-
in
|
|
29
|
+
in RFC 7748.
|
|
30
30
|
email:
|
|
31
31
|
- bascule@gmail.com
|
|
32
32
|
executables: []
|
|
33
33
|
extensions:
|
|
34
|
-
- ext/
|
|
34
|
+
- ext/x25519_precomputed/extconf.rb
|
|
35
|
+
- ext/x25519_ref10/extconf.rb
|
|
35
36
|
extra_rdoc_files: []
|
|
36
37
|
files:
|
|
37
38
|
- ".gitignore"
|
|
@@ -44,33 +45,39 @@ files:
|
|
|
44
45
|
- LICENSE
|
|
45
46
|
- README.md
|
|
46
47
|
- Rakefile
|
|
47
|
-
- ext/
|
|
48
|
-
- ext/
|
|
49
|
-
- ext/
|
|
50
|
-
- ext/
|
|
51
|
-
- ext/
|
|
52
|
-
- ext/
|
|
53
|
-
- ext/
|
|
54
|
-
- ext/
|
|
55
|
-
- ext/
|
|
56
|
-
- ext/
|
|
57
|
-
- ext/
|
|
58
|
-
- ext/
|
|
59
|
-
- ext/
|
|
60
|
-
- ext/
|
|
61
|
-
- ext/
|
|
62
|
-
- ext/
|
|
63
|
-
- ext/
|
|
64
|
-
- ext/
|
|
65
|
-
- ext/
|
|
66
|
-
- ext/
|
|
67
|
-
- ext/
|
|
68
|
-
- ext/
|
|
69
|
-
- ext/
|
|
70
|
-
- ext/
|
|
71
|
-
- ext/
|
|
72
|
-
- ext/
|
|
73
|
-
- ext/
|
|
48
|
+
- ext/x25519_precomputed/cputest.c
|
|
49
|
+
- ext/x25519_precomputed/extconf.rb
|
|
50
|
+
- ext/x25519_precomputed/fp25519_x64.c
|
|
51
|
+
- ext/x25519_precomputed/fp25519_x64.h
|
|
52
|
+
- ext/x25519_precomputed/table_ladder_x25519.h
|
|
53
|
+
- ext/x25519_precomputed/x25519_precomputed.c
|
|
54
|
+
- ext/x25519_precomputed/x25519_precomputed.h
|
|
55
|
+
- ext/x25519_precomputed/x25519_x64.c
|
|
56
|
+
- ext/x25519_ref10/api.h
|
|
57
|
+
- ext/x25519_ref10/base.c
|
|
58
|
+
- ext/x25519_ref10/extconf.rb
|
|
59
|
+
- ext/x25519_ref10/fe.h
|
|
60
|
+
- ext/x25519_ref10/fe_0.c
|
|
61
|
+
- ext/x25519_ref10/fe_1.c
|
|
62
|
+
- ext/x25519_ref10/fe_add.c
|
|
63
|
+
- ext/x25519_ref10/fe_copy.c
|
|
64
|
+
- ext/x25519_ref10/fe_cswap.c
|
|
65
|
+
- ext/x25519_ref10/fe_frombytes.c
|
|
66
|
+
- ext/x25519_ref10/fe_invert.c
|
|
67
|
+
- ext/x25519_ref10/fe_mul.c
|
|
68
|
+
- ext/x25519_ref10/fe_mul121666.c
|
|
69
|
+
- ext/x25519_ref10/fe_sq.c
|
|
70
|
+
- ext/x25519_ref10/fe_sub.c
|
|
71
|
+
- ext/x25519_ref10/fe_tobytes.c
|
|
72
|
+
- ext/x25519_ref10/montgomery.h
|
|
73
|
+
- ext/x25519_ref10/pow225521.h
|
|
74
|
+
- ext/x25519_ref10/scalarmult.c
|
|
75
|
+
- ext/x25519_ref10/x25519_ref10.c
|
|
76
|
+
- ext/x25519_ref10/x25519_ref10.h
|
|
77
|
+
- lib/x25519.rb
|
|
78
|
+
- lib/x25519/montgomery_u.rb
|
|
79
|
+
- lib/x25519/scalar.rb
|
|
80
|
+
- lib/x25519/version.rb
|
|
74
81
|
- x25519.gemspec
|
|
75
82
|
homepage: https://github.com/cryptosphere/x25519
|
|
76
83
|
licenses:
|
data/ext/x25519/extconf.rb
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# rubocop:disable Style/GlobalVars
|
|
4
|
-
|
|
5
|
-
require "mkmf"
|
|
6
|
-
|
|
7
|
-
abort("missing posix_memalign()") unless have_func("posix_memalign", "stdlib.h")
|
|
8
|
-
|
|
9
|
-
$INCFLAGS << " -I$(srcdir)/ref10 -I$(srcdir)/rfc7748_precomputed"
|
|
10
|
-
|
|
11
|
-
# Check for Intel 4th Gen Core CPU features
|
|
12
|
-
# TODO: move this detection completely to runtime
|
|
13
|
-
cputest_c = <<SRC
|
|
14
|
-
#{File.read(File.expand_path('cputest.c', __dir__))}
|
|
15
|
-
int main() {
|
|
16
|
-
return check_4th_gen_intel_core_features() != 1;
|
|
17
|
-
}
|
|
18
|
-
SRC
|
|
19
|
-
|
|
20
|
-
if try_run(cputest_c)
|
|
21
|
-
$defs.push("-DHAVE_4TH_GEN_INTEL_CORE")
|
|
22
|
-
$CFLAGS << " -Wall -O3 -pedantic -std=c99 -mbmi -mbmi2 -march=native -mtune=native"
|
|
23
|
-
$srcs = Dir.glob(File.join(__dir__, "**", "*.c"))
|
|
24
|
-
else
|
|
25
|
-
# Do not include the rfc7748_precomputed sources if we do not have a 4th gen+ Core CPU
|
|
26
|
-
$srcs = Dir.glob(File.join(__dir__, "*.c")) + Dir.glob(File.expand_path("ref10/*.c", __dir__))
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
$objs = $srcs.map { |src| src.sub(/\.c$/, ".o") }
|
|
30
|
-
|
|
31
|
-
create_makefile "x25519"
|
data/ext/x25519/x25519.c
DELETED
|
@@ -1,325 +0,0 @@
|
|
|
1
|
-
/* Ruby C extension providing bindings to the X25519 Diffie-Hellman algorithm */
|
|
2
|
-
|
|
3
|
-
#define _POSIX_C_SOURCE 200809L
|
|
4
|
-
#include <stdlib.h>
|
|
5
|
-
|
|
6
|
-
#include "ruby.h"
|
|
7
|
-
#include "x25519.h"
|
|
8
|
-
|
|
9
|
-
/* The X25519::VERSION */
|
|
10
|
-
#define GEM_VERSION "0.1.0"
|
|
11
|
-
|
|
12
|
-
/* X25519 module method prototypes */
|
|
13
|
-
static VALUE X25519_backend(VALUE self);
|
|
14
|
-
static VALUE X25519_self_test(VALUE self);
|
|
15
|
-
static VALUE X25519_diffie_hellman(VALUE self, VALUE public_key, VALUE secret_key);
|
|
16
|
-
|
|
17
|
-
/* X25519::Scalar prototypes */
|
|
18
|
-
static VALUE cX25519_Scalar_allocate(VALUE klass);
|
|
19
|
-
static void cX25519_Scalar_mark(X25519_KEY *scalar);
|
|
20
|
-
static void cX25519_Scalar_free(X25519_KEY *scalar);
|
|
21
|
-
static VALUE cX25519_Scalar_generate(VALUE self);
|
|
22
|
-
static VALUE cX25519_Scalar_initialize(VALUE self, VALUE bytes);
|
|
23
|
-
static VALUE cX25519_Scalar_multiply_base(VALUE self);
|
|
24
|
-
static VALUE cX25519_Scalar_multiply(VALUE self, VALUE montgomery_u);
|
|
25
|
-
static VALUE cX25519_Scalar_to_bytes(VALUE self);
|
|
26
|
-
|
|
27
|
-
/* X25519::MontgomeryU prototypes */
|
|
28
|
-
static VALUE cX25519_MontgomeryU_allocate(VALUE klass);
|
|
29
|
-
static void cX25519_MontgomeryU_mark(X25519_KEY *coord);
|
|
30
|
-
static void cX25519_MontgomeryU_free(X25519_KEY *coord);
|
|
31
|
-
static VALUE cX25519_MontgomeryU_initialize(VALUE self, VALUE bytes);
|
|
32
|
-
static VALUE cX25519_MontgomeryU_to_bytes(VALUE self);
|
|
33
|
-
|
|
34
|
-
static VALUE mX25519 = Qnil;
|
|
35
|
-
static VALUE cX25519_Scalar = Qnil;
|
|
36
|
-
static VALUE cX25519_MontgomeryU = Qnil;
|
|
37
|
-
|
|
38
|
-
/* Are we on a 4th gen Intel Core CPU architecture that supports the
|
|
39
|
-
rfc7748_precomputed backend? */
|
|
40
|
-
static int use_rfc7748_precomputed = 0;
|
|
41
|
-
|
|
42
|
-
/* Initialize the Ruby module */
|
|
43
|
-
void Init_x25519()
|
|
44
|
-
{
|
|
45
|
-
/* Test for support for the rfc7748_precomputed backend */
|
|
46
|
-
use_rfc7748_precomputed = check_4th_gen_intel_core_features();
|
|
47
|
-
|
|
48
|
-
/* Used for key generation */
|
|
49
|
-
rb_require("securerandom");
|
|
50
|
-
|
|
51
|
-
mX25519 = rb_define_module("X25519");
|
|
52
|
-
rb_define_const(mX25519, "VERSION", rb_str_new2(GEM_VERSION));
|
|
53
|
-
rb_define_singleton_method(mX25519, "backend", X25519_backend, 0);
|
|
54
|
-
rb_define_singleton_method(mX25519, "self_test", X25519_self_test, 0);
|
|
55
|
-
rb_define_singleton_method(mX25519, "diffie_hellman", X25519_diffie_hellman, 2);
|
|
56
|
-
|
|
57
|
-
cX25519_Scalar = rb_define_class_under(mX25519, "Scalar", rb_cObject);
|
|
58
|
-
rb_define_alloc_func(cX25519_Scalar, cX25519_Scalar_allocate);
|
|
59
|
-
rb_define_singleton_method(cX25519_Scalar, "generate", cX25519_Scalar_generate, 0);
|
|
60
|
-
rb_define_method(cX25519_Scalar, "initialize", cX25519_Scalar_initialize, 1);
|
|
61
|
-
rb_define_method(cX25519_Scalar, "multiply_base", cX25519_Scalar_multiply_base, 0);
|
|
62
|
-
rb_define_method(cX25519_Scalar, "public_key", cX25519_Scalar_multiply_base, 0);
|
|
63
|
-
rb_define_method(cX25519_Scalar, "multiply", cX25519_Scalar_multiply, 1);
|
|
64
|
-
rb_define_method(cX25519_Scalar, "diffie_hellman", cX25519_Scalar_multiply, 1);
|
|
65
|
-
rb_define_method(cX25519_Scalar, "to_bytes", cX25519_Scalar_to_bytes, 0);
|
|
66
|
-
rb_define_method(cX25519_Scalar, "to_str", cX25519_Scalar_to_bytes, 0);
|
|
67
|
-
|
|
68
|
-
cX25519_MontgomeryU = rb_define_class_under(mX25519, "MontgomeryU", rb_cObject);
|
|
69
|
-
rb_define_alloc_func(cX25519_MontgomeryU, cX25519_MontgomeryU_allocate);
|
|
70
|
-
rb_define_method(cX25519_MontgomeryU, "initialize", cX25519_MontgomeryU_initialize, 1);
|
|
71
|
-
rb_define_method(cX25519_MontgomeryU, "to_bytes", cX25519_MontgomeryU_to_bytes, 0);
|
|
72
|
-
rb_define_method(cX25519_MontgomeryU, "to_str", cX25519_MontgomeryU_to_bytes, 0);
|
|
73
|
-
|
|
74
|
-
/* Run the self-test on load to ensure everything is working */
|
|
75
|
-
rb_funcall(mX25519, rb_intern("self_test"), 0);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/* Return a symbol identifying the backend in use */
|
|
79
|
-
static VALUE X25519_backend(VALUE self)
|
|
80
|
-
{
|
|
81
|
-
switch(use_rfc7748_precomputed) {
|
|
82
|
-
case 1:
|
|
83
|
-
return ID2SYM(rb_intern("rfc7748_precomputed"));
|
|
84
|
-
case 0:
|
|
85
|
-
return ID2SYM(rb_intern("ref10"));
|
|
86
|
-
default:
|
|
87
|
-
rb_raise(rb_eRuntimeError, "invalid X25519 backend! (%d)", use_rfc7748_precomputed);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/* Perform an end-to-end test of the Ruby binding to ensure it's working correctly */
|
|
92
|
-
static VALUE X25519_self_test(VALUE self)
|
|
93
|
-
{
|
|
94
|
-
VALUE sk, pk, shared;
|
|
95
|
-
|
|
96
|
-
/* Test vectors from RFC 7748 */
|
|
97
|
-
X25519_KEY ietf_cfrg_key0 = {
|
|
98
|
-
0xa5,0x46,0xe3,0x6b,0xf0,0x52,0x7c,0x9d,
|
|
99
|
-
0x3b,0x16,0x15,0x4b,0x82,0x46,0x5e,0xdd,
|
|
100
|
-
0x62,0x14,0x4c,0x0a,0xc1,0xfc,0x5a,0x18,
|
|
101
|
-
0x50,0x6a,0x22,0x44,0xba,0x44,0x9a,0xc4
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
X25519_KEY ietf_cfrg_input_coord0 = {
|
|
105
|
-
0xe6,0xdb,0x68,0x67,0x58,0x30,0x30,0xdb,
|
|
106
|
-
0x35,0x94,0xc1,0xa4,0x24,0xb1,0x5f,0x7c,
|
|
107
|
-
0x72,0x66,0x24,0xec,0x26,0xb3,0x35,0x3b,
|
|
108
|
-
0x10,0xa9,0x03,0xa6,0xd0,0xab,0x1c,0x4c
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
X25519_KEY ietf_cfrg_output_coord0 = {
|
|
112
|
-
0xc3,0xda,0x55,0x37,0x9d,0xe9,0xc6,0x90,
|
|
113
|
-
0x8e,0x94,0xea,0x4d,0xf2,0x8d,0x08,0x4f,
|
|
114
|
-
0x32,0xec,0xcf,0x03,0x49,0x1c,0x71,0xf7,
|
|
115
|
-
0x54,0xb4,0x07,0x55,0x77,0xa2,0x85,0x52
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
sk = rb_str_new((const char *)&ietf_cfrg_key0, X25519_KEYSIZE_BYTES);
|
|
119
|
-
pk = rb_str_new((const char *)&ietf_cfrg_input_coord0, X25519_KEYSIZE_BYTES);
|
|
120
|
-
|
|
121
|
-
shared = rb_funcall(mX25519, rb_intern("diffie_hellman"), 2, sk, pk);
|
|
122
|
-
|
|
123
|
-
if(RSTRING_LEN(shared) != X25519_KEYSIZE_BYTES ||
|
|
124
|
-
memcmp(RSTRING_PTR(shared), ietf_cfrg_output_coord0, X25519_KEYSIZE_BYTES) != 0)
|
|
125
|
-
{
|
|
126
|
-
rb_raise(rb_eRuntimeError, "X25519 self-test failed!");
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return Qtrue;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/* Compute Diffie-Hellman for the given key and Montgomery-u coordinate
|
|
133
|
-
* (i.e. variable base scalar multiplication) */
|
|
134
|
-
static VALUE X25519_diffie_hellman(VALUE self, VALUE secret_key, VALUE public_key)
|
|
135
|
-
{
|
|
136
|
-
VALUE scalar, coord, shared;
|
|
137
|
-
|
|
138
|
-
scalar = rb_class_new_instance(1, &secret_key, cX25519_Scalar);
|
|
139
|
-
coord = rb_class_new_instance(1, &public_key, cX25519_MontgomeryU);
|
|
140
|
-
shared = rb_funcall(scalar, rb_intern("multiply"), 1, coord);
|
|
141
|
-
|
|
142
|
-
return rb_funcall(shared, rb_intern("to_bytes"), 0);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/********************************
|
|
146
|
-
* X25519::Scalar: private keys *
|
|
147
|
-
********************************/
|
|
148
|
-
|
|
149
|
-
static VALUE cX25519_Scalar_allocate(VALUE klass)
|
|
150
|
-
{
|
|
151
|
-
X25519_KEY *scalar = NULL;
|
|
152
|
-
|
|
153
|
-
/* Ensure allocation with the correct (32-byte) memory alignent */
|
|
154
|
-
if(posix_memalign((void **)&scalar, ALIGN_BYTES, X25519_KEYSIZE_BYTES)) {
|
|
155
|
-
rb_fatal("x25519: can't allocate memory with posix_memalign()");
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/* Avoid using unitialized memory */
|
|
159
|
-
memset(scalar, 0, X25519_KEYSIZE_BYTES);
|
|
160
|
-
|
|
161
|
-
return Data_Wrap_Struct(klass, cX25519_Scalar_mark, cX25519_Scalar_free, scalar);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
static void cX25519_Scalar_mark(X25519_KEY *scalar)
|
|
165
|
-
{
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
static void cX25519_Scalar_free(X25519_KEY *scalar)
|
|
169
|
-
{
|
|
170
|
-
free(scalar);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/* Generate a random X25519 private scalar */
|
|
174
|
-
static VALUE cX25519_Scalar_generate(VALUE self)
|
|
175
|
-
{
|
|
176
|
-
VALUE rb_mSecureRandom, scalar_bytes;
|
|
177
|
-
rb_mSecureRandom = rb_const_get(rb_cObject, rb_intern("SecureRandom"));
|
|
178
|
-
|
|
179
|
-
scalar_bytes = rb_funcall(
|
|
180
|
-
rb_mSecureRandom,
|
|
181
|
-
rb_intern("random_bytes"),
|
|
182
|
-
1,
|
|
183
|
-
INT2NUM(X25519_KEYSIZE_BYTES)
|
|
184
|
-
);
|
|
185
|
-
|
|
186
|
-
return rb_class_new_instance(1, &scalar_bytes, self);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/* Create an X25519::Scalar from a String containing bytes */
|
|
190
|
-
static VALUE cX25519_Scalar_initialize(VALUE self, VALUE bytes)
|
|
191
|
-
{
|
|
192
|
-
X25519_KEY *scalar = NULL;
|
|
193
|
-
Data_Get_Struct(self, X25519_KEY, scalar);
|
|
194
|
-
|
|
195
|
-
StringValue(bytes);
|
|
196
|
-
if(RSTRING_LEN(bytes) != X25519_KEYSIZE_BYTES) {
|
|
197
|
-
rb_raise(
|
|
198
|
-
rb_eArgError,
|
|
199
|
-
"expected %d-byte scalar, got %ld",
|
|
200
|
-
X25519_KEYSIZE_BYTES,
|
|
201
|
-
RSTRING_LEN(bytes)
|
|
202
|
-
);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
memcpy(scalar, RSTRING_PTR(bytes), X25519_KEYSIZE_BYTES);
|
|
206
|
-
|
|
207
|
-
return self;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/* Obtain a public key for an X25519 private scalar
|
|
211
|
-
* (i.e. fixed base scalar multiplication ) */
|
|
212
|
-
static VALUE cX25519_Scalar_multiply_base(VALUE self)
|
|
213
|
-
{
|
|
214
|
-
X25519_KEY *scalar = NULL, public_key;
|
|
215
|
-
VALUE public_key_str;
|
|
216
|
-
|
|
217
|
-
Data_Get_Struct(self, X25519_KEY, scalar);
|
|
218
|
-
|
|
219
|
-
/* Avoid using unitialized memory */
|
|
220
|
-
memset(&public_key, 0, X25519_KEYSIZE_BYTES);
|
|
221
|
-
|
|
222
|
-
/* Compute public key from private scalar using fixed-base scalar multiplication */
|
|
223
|
-
if(use_rfc7748_precomputed) {
|
|
224
|
-
x25519_rfc7748_precomputed_scalarmult_base(public_key, *scalar);
|
|
225
|
-
} else {
|
|
226
|
-
x25519_ref10_scalarmult_base(public_key, *scalar);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
public_key_str = rb_str_new((const char *)&public_key, X25519_KEYSIZE_BYTES);
|
|
230
|
-
return rb_class_new_instance(1, &public_key_str, cX25519_MontgomeryU);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/* Obtain a public key for an X25519 private scalar
|
|
234
|
-
* (i.e. fixed base scalar multiplication ) */
|
|
235
|
-
static VALUE cX25519_Scalar_multiply(VALUE self, VALUE montgomery_u)
|
|
236
|
-
{
|
|
237
|
-
X25519_KEY *scalar = NULL, *coord = NULL, product;
|
|
238
|
-
VALUE product_str;
|
|
239
|
-
|
|
240
|
-
if(rb_obj_class(montgomery_u) != cX25519_MontgomeryU) {
|
|
241
|
-
rb_raise(rb_eTypeError, "wrong argument type (expected X25519::MontgomeryU)");
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
Data_Get_Struct(self, X25519_KEY, scalar);
|
|
245
|
-
Data_Get_Struct(montgomery_u, X25519_KEY, coord);
|
|
246
|
-
|
|
247
|
-
/* Avoid using unitialized memory */
|
|
248
|
-
memset(&product, 0, X25519_KEYSIZE_BYTES);
|
|
249
|
-
|
|
250
|
-
/* Compute the Diffie-Hellman shared secret */
|
|
251
|
-
if(use_rfc7748_precomputed) {
|
|
252
|
-
x25519_rfc7748_precomputed_scalarmult(product, *scalar, *coord);
|
|
253
|
-
} else {
|
|
254
|
-
x25519_ref10_scalarmult(product, *scalar, *coord);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
product_str = rb_str_new((const char *)&product, X25519_KEYSIZE_BYTES);
|
|
258
|
-
return rb_class_new_instance(1, &product_str, cX25519_MontgomeryU);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/* Return a String containing the raw bytes of this scalar */
|
|
262
|
-
static VALUE cX25519_Scalar_to_bytes(VALUE self)
|
|
263
|
-
{
|
|
264
|
-
X25519_KEY *scalar = NULL;
|
|
265
|
-
Data_Get_Struct(self, X25519_KEY, scalar);
|
|
266
|
-
|
|
267
|
-
return rb_str_new((const char *)scalar, X25519_KEYSIZE_BYTES);;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
/************************************
|
|
271
|
-
* X25519::MontgomeryU: public keys *
|
|
272
|
-
************************************/
|
|
273
|
-
|
|
274
|
-
static VALUE cX25519_MontgomeryU_allocate(VALUE klass)
|
|
275
|
-
{
|
|
276
|
-
X25519_KEY *coord = NULL;
|
|
277
|
-
|
|
278
|
-
/* Ensure allocation with the correct (32-byte) memory alignent */
|
|
279
|
-
if(posix_memalign((void **)&coord, ALIGN_BYTES, X25519_KEYSIZE_BYTES)) {
|
|
280
|
-
rb_fatal("x25519: can't allocate memory with posix_memalign()");
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/* Avoid using unitialized memory */
|
|
284
|
-
memset(coord, 0, X25519_KEYSIZE_BYTES);
|
|
285
|
-
|
|
286
|
-
return Data_Wrap_Struct(klass, cX25519_MontgomeryU_mark, cX25519_MontgomeryU_free, coord);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
static void cX25519_MontgomeryU_mark(X25519_KEY *coord)
|
|
290
|
-
{
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
static void cX25519_MontgomeryU_free(X25519_KEY *coord)
|
|
294
|
-
{
|
|
295
|
-
free(coord);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
static VALUE cX25519_MontgomeryU_initialize(VALUE self, VALUE bytes)
|
|
299
|
-
{
|
|
300
|
-
X25519_KEY *coord = NULL;
|
|
301
|
-
Data_Get_Struct(self, X25519_KEY, coord);
|
|
302
|
-
|
|
303
|
-
StringValue(bytes);
|
|
304
|
-
if(RSTRING_LEN(bytes) != X25519_KEYSIZE_BYTES) {
|
|
305
|
-
rb_raise(
|
|
306
|
-
rb_eArgError,
|
|
307
|
-
"expected %d-byte scalar, got %ld",
|
|
308
|
-
X25519_KEYSIZE_BYTES,
|
|
309
|
-
RSTRING_LEN(bytes)
|
|
310
|
-
);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
memcpy(coord, RSTRING_PTR(bytes), X25519_KEYSIZE_BYTES);
|
|
314
|
-
|
|
315
|
-
return self;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
/* Return a String containing the raw bytes of this scalar */
|
|
319
|
-
static VALUE cX25519_MontgomeryU_to_bytes(VALUE self)
|
|
320
|
-
{
|
|
321
|
-
X25519_KEY *coord = NULL;
|
|
322
|
-
Data_Get_Struct(self, X25519_KEY, coord);
|
|
323
|
-
|
|
324
|
-
return rb_str_new((const char *)coord, X25519_KEYSIZE_BYTES);;
|
|
325
|
-
}
|
data/ext/x25519/x25519.h
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
#include "rfc7748_precomputed.h"
|
|
2
|
-
|
|
3
|
-
/* Detect support for 4th gen (e.g. Haswell) or newer CPUs */
|
|
4
|
-
int check_4th_gen_intel_core_features();
|
|
5
|
-
|
|
6
|
-
/**********************************
|
|
7
|
-
* rfc7748_precomputed prototypes *
|
|
8
|
-
**********************************/
|
|
9
|
-
|
|
10
|
-
/* Fixed-base scalar multiplication */
|
|
11
|
-
void x25519_rfc7748_precomputed_scalarmult_base(uint8_t *session_key, uint8_t *private_key);
|
|
12
|
-
|
|
13
|
-
/* Variable-base scalar multiplication */
|
|
14
|
-
void x25519_rfc7748_precomputed_scalarmult(uint8_t *shared, uint8_t *private_key, uint8_t *session_key);
|
|
15
|
-
|
|
16
|
-
/********************
|
|
17
|
-
* ref10 prototypes *
|
|
18
|
-
********************/
|
|
19
|
-
|
|
20
|
-
/* Fixed-base scalar multiplication */
|
|
21
|
-
int x25519_ref10_scalarmult_base(uint8_t *q, const uint8_t *n);
|
|
22
|
-
|
|
23
|
-
/* Variable-base scalar multiplication */
|
|
24
|
-
int x25519_ref10_scalarmult(uint8_t *q, const uint8_t *n, const uint8_t *p);
|