sygna 0.1.3 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
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