sygna 0.1.3 → 0.1.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a75991d67a893ff92a864d26baedbfb012eb3762b3fe64eeaa82e3342aab64f7
4
- data.tar.gz: 1c01825849fb2ba32811dcaa167de8fbc39c21f320b1d4cce4e62e4560c8658b
3
+ metadata.gz: 207581b951aa254c6b3db5d358a28ea78130312d96f480ecd0917c2729c9c5e0
4
+ data.tar.gz: 4f4257a9ac614e9d77c686eae821929112c6e6057de2bdc9f1e1a9f1ecf247a3
5
5
  SHA512:
6
- metadata.gz: e514458cd2e75782bfc5ff776370b59d8464fa32900cada13463e2ee728d62dc7684c7954f1f70bd61a6069dbea2892685870d1b7f17e31a2ae1f462b738cd0f
7
- data.tar.gz: 77b4c48fc647d006dd679072c04574781d288203ce232a2e4fc694731c0b80550cc8d0221008d8133a7ac775f1a30823d37a8e1e92cda001daf7c20e2297c18b
6
+ metadata.gz: 74b1331f0a72b5ab457394f078fc6a19fe08cc8665140e59c84669a9859c74396ce19963a627f11f2f986d7b4d32a98e1782050b8d93277d086af915c97c41c2
7
+ data.tar.gz: 2d6f3f64d2d5c117ee1d7faba488bcf91fd3887c10a6d57ee8d86b1f7cda5398a6be99005bb6f6054b627b67dbe5802e2203947d367e7fbcfb50b944ac1d36e4
data/lib/sygna/crypt.rb CHANGED
@@ -25,32 +25,14 @@ module Sygna
25
25
  # {CIPHERS}.
26
26
  # @param digest [String,OpenSSL::Digest] The digest algorithm to use for
27
27
  # HMAC and KDF. Must be one of {DIGESTS}.
28
- # @param mac_length [:half,:full] The length of the mac. If :half, the mac
29
- # length will be equal to half the mac_digest's digest_legnth. If
30
- # :full, the mac length will be equal to the mac_digest's
31
- # digest_length.
32
- # @param kdf_digest [String,OpenSSL::Digest,nil] The digest algorithm to
33
- # use for KDF. If not specified, the `digest` argument will be used.
34
28
  # @param mac_digest [String,OpenSSL::Digest,nil] The digest algorithm to
35
29
  # use for HMAC. If not specified, the `digest` argument will be used.
36
- # @param kdf_shared_info [String] Optional. A string containing the shared
37
- # info used for KDF, also known as SharedInfo1.
38
- # @param mac_shared_info [String] Optional. A string containing the shared
39
- # info used for MAC, also known as SharedInfo2.
40
- def initialize(cipher: 'AES-256-CTR', digest: 'SHA256', mac_length: :half, kdf_digest: nil, mac_digest: nil, kdf_shared_info: '', mac_shared_info: '')
30
+ def initialize(cipher: 'AES-256-CTR', digest: 'SHA256', mac_digest: nil)
41
31
  @cipher = OpenSSL::Cipher.new(cipher)
42
32
  @mac_digest = OpenSSL::Digest.new(mac_digest || digest)
43
- @kdf_digest = OpenSSL::Digest.new(kdf_digest || digest)
44
- @kdf_shared_info = kdf_shared_info
45
- @mac_shared_info = mac_shared_info
46
33
 
47
34
  CIPHERS.include?(@cipher.name) or raise "Cipher must be one of #{CIPHERS}"
48
35
  DIGESTS.include?(@mac_digest.name) or raise "Digest must be one of #{DIGESTS}"
49
- DIGESTS.include?(@kdf_digest.name) or raise "Digest must be one of #{DIGESTS}"
50
- [:half, :full].include?(mac_length) or raise "mac_length must be :half or :full"
51
-
52
- @mac_length = @mac_digest.digest_length
53
- @mac_length /= 2 if mac_length == :half
54
36
  end
55
37
 
56
38
  # Encrypts a message to a public key using ECIES.
@@ -63,23 +45,27 @@ module Sygna
63
45
  @cipher.reset
64
46
 
65
47
  group_copy = OpenSSL::PKey::EC::Group.new(key.group)
66
- group_copy.point_conversion_form = :compressed
48
+
67
49
  ephemeral_key = OpenSSL::PKey::EC.new(group_copy).generate_key
68
50
  ephemeral_public_key_octet = ephemeral_key.public_key.to_bn.to_s(2)
69
51
 
70
52
  shared_secret = ephemeral_key.dh_compute_key(key.public_key)
71
53
 
72
- key_pair = kdf(shared_secret, @cipher.key_len + @mac_length, ephemeral_public_key_octet)
73
- cipher_key = key_pair.byteslice(0, @cipher.key_len)
74
- hmac_key = key_pair.byteslice(-@mac_length, @mac_length)
54
+ hashed_secret = Digest::SHA512.digest(shared_secret)
55
+
56
+ cipher_key = hashed_secret.slice(0, 32)
57
+ hmac_key = hashed_secret.slice(32, hashed_secret.length - 32)
75
58
 
76
59
  @cipher.encrypt
77
60
  @cipher.iv = IV
78
61
  @cipher.key = cipher_key
79
62
  ciphertext = @cipher.update(message) + @cipher.final
80
63
 
81
- mac = OpenSSL::HMAC.digest(@mac_digest, hmac_key, ciphertext + @mac_shared_info).byteslice(0, @mac_length)
64
+ data_to_mac = IV + ephemeral_public_key_octet + ciphertext
82
65
 
66
+ mac = OpenSSL::HMAC.digest(@mac_digest, hmac_key, data_to_mac)
67
+
68
+ # 65 + 20 + 16
83
69
  ephemeral_public_key_octet + mac + ciphertext
84
70
  end
85
71
 
@@ -93,25 +79,25 @@ module Sygna
93
79
  @cipher.reset
94
80
 
95
81
  group_copy = OpenSSL::PKey::EC::Group.new(key.group)
96
- group_copy.point_conversion_form = :compressed
97
82
 
98
- ephemeral_public_key_length = group_copy.generator.to_bn.to_s(2).bytesize
99
- ciphertext_length = encrypted_message.bytesize - ephemeral_public_key_length - @mac_length
100
- ciphertext_length > 0 or raise OpenSSL::PKey::ECError, "Encrypted message too short"
83
+ ephemeral_public_key_octet = encrypted_message.slice(0, 65)
84
+
85
+ mac = encrypted_message.slice(65, 20)
101
86
 
102
- ephemeral_public_key_octet = encrypted_message.byteslice(0, ephemeral_public_key_length)
103
- ciphertext = encrypted_message.byteslice(ephemeral_public_key_length, ciphertext_length)
104
- mac = encrypted_message.byteslice(-@mac_length, @mac_length)
87
+ ciphertext = encrypted_message.slice(85, encrypted_message.size)
105
88
 
106
89
  ephemeral_public_key = OpenSSL::PKey::EC::Point.new(group_copy, OpenSSL::BN.new(ephemeral_public_key_octet, 2))
107
90
 
108
91
  shared_secret = key.dh_compute_key(ephemeral_public_key)
109
92
 
110
- key_pair = kdf(shared_secret, @cipher.key_len + @mac_length, ephemeral_public_key_octet)
111
- cipher_key = key_pair.byteslice(0, @cipher.key_len)
112
- hmac_key = key_pair.byteslice(-@mac_length, @mac_length)
93
+ hashed_secret = Digest::SHA512.digest(shared_secret)
94
+
95
+ cipher_key = hashed_secret.slice(0, 32)
96
+ hmac_key = hashed_secret.slice(32, hashed_secret.length)
113
97
 
114
- computed_mac = OpenSSL::HMAC.digest(@mac_digest, hmac_key, ciphertext + @mac_shared_info).byteslice(0, @mac_length)
98
+ data_to_mac = IV + ephemeral_public_key_octet + ciphertext
99
+
100
+ computed_mac = OpenSSL::HMAC.digest("SHA1", hmac_key, data_to_mac)
115
101
  computed_mac == mac or raise OpenSSL::PKey::ECError, "Invalid Message Authenticaton Code"
116
102
 
117
103
  @cipher.decrypt
@@ -121,43 +107,6 @@ module Sygna
121
107
  @cipher.update(ciphertext) + @cipher.final
122
108
  end
123
109
 
124
- # Key-derivation function, compatible with ANSI-X9.63-KDF
125
- #
126
- # @param shared_secret [String] The shared secret from which the key will
127
- # be derived.
128
- # @param length [Integer] The length of the key to generate.
129
- # @param shared_info_suffix [String] The suffix to append to the
130
- # shared_info.
131
- # @return [String] Octet string of the derived key.
132
- def kdf(shared_secret, length, shared_info_suffix)
133
- length >=0 or raise "length cannot be negative"
134
- return "" if length == 0
135
-
136
- if length / @kdf_digest.digest_length >= 0xFF_FF_FF_FF
137
- raise "length too large"
138
- end
139
-
140
- io = StringIO.new(String.new)
141
- counter = 0
142
-
143
- loop do
144
- counter += 1
145
- counter_bytes = [counter].pack('N')
146
-
147
- io << @kdf_digest.digest(shared_secret + counter_bytes + @kdf_shared_info + shared_info_suffix)
148
- if io.pos >= length
149
- return io.string.byteslice(0, length)
150
- end
151
- end
152
- end
153
-
154
- # @return [String] A string representing this Crypt's parameters.
155
- def to_s
156
- "KDF-#{@kdf_digest.name}_" +
157
- "HMAC-SHA-#{@mac_digest.digest_length * 8}-#{@mac_length * 8}_" +
158
- @cipher.name
159
- end
160
-
161
110
  # Converts a hex-encoded public key to an `OpenSSL::PKey::EC`.
162
111
  #
163
112
  # @param hex_string [String] The hex-encoded public key.
@@ -8,14 +8,18 @@ module Sygna
8
8
  Secp256k1::Utils.encode_hex(ecdsa_private_key.ecdsa_serialize_compact(ecdsa_private_key.ecdsa_sign(object_string)))
9
9
  end
10
10
 
11
- def self.verify(object, signature)
11
+ def self.verify(object, signature, public_key)
12
12
  object_string = object.merge(EMPTY_SIGNATURE).to_json
13
13
 
14
14
  raw_signature = Secp256k1::Utils.decode_hex(signature)
15
15
 
16
- signature = ecdsa_private_key.pubkey.ecdsa_deserialize_compact(raw_signature)
16
+ public_key_binary = [public_key].pack("H*")
17
17
 
18
- ecdsa_private_key.pubkey.ecdsa_verify(object_string, signature)
18
+ ecdsa_public_key = Secp256k1::PublicKey.new(pubkey: public_key)
19
+
20
+ signature = ecdsa_public_key.ecdsa_deserialize_compact(raw_signature)
21
+
22
+ ecdsa_public_key.ecdsa_verify(object_string, signature)
19
23
  end
20
24
 
21
25
  def self.ecdsa_private_key
data/lib/sygna/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Sygna
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.7"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sygna
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nic
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-04-06 00:00:00.000000000 Z
11
+ date: 2020-04-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler