ecies 0.2.0 → 0.4.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
- checksums.yaml.gz.sig +2 -2
- data/.gitignore +1 -0
- data/CHANGELOG.md +25 -1
- data/README.md +12 -11
- data/certs/jamoes.pem +23 -18
- data/ecies.gemspec +2 -5
- data/lib/ecies/crypt.rb +44 -37
- data/lib/ecies/version.rb +1 -1
- data/lib/ecies.rb +3 -2
- data/spec/crypt_spec.rb +61 -65
- data.tar.gz.sig +0 -0
- metadata +32 -28
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ccdc4376e7e505685dafd7456609bee87adb7909ee863dea0a02a46bc10ea9ec
|
|
4
|
+
data.tar.gz: c2c8c601e446e361ea28d9605108ba52b5df6d3444b20093f410ac6cee73621a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 14dcb2ccec245e71d68eb63b520d320c6e39b330a2f01fd59848ce9ff0d6436d90e100eb5b5857bda40b780dedf365d2bfc4f14dbca9ca8b612560bb82a5c111
|
|
7
|
+
data.tar.gz: dd259230ce124924f5269b1fbb966ea17207ee41dcc206669d1eccc74e62ccd35803f9c96c869011333526cf5c8a03175d671abbf27356d117e5502d42e54d51
|
checksums.yaml.gz.sig
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
�������=xu8
|
|
2
|
+
x��;���Y�E�D]B��'�Z�����r���c$�{1�L���kWm�ѓ����2E��6z�p���
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -4,9 +4,33 @@ Change log
|
|
|
4
4
|
This gem follows [Semantic Versioning 2.0.0](http://semver.org/spec/v2.0.0.html).
|
|
5
5
|
All classes and public methods are part of the public API.
|
|
6
6
|
|
|
7
|
+
0.4.0
|
|
8
|
+
---
|
|
9
|
+
Released on 2023-06-20
|
|
10
|
+
|
|
11
|
+
- Add support for OpenSSL 3.0.
|
|
12
|
+
- Remove `Crypt.private_key_from_hex` method.
|
|
13
|
+
- Users can still utilize `OpenSSL::PKey::EC.new` to construct a PKey.
|
|
14
|
+
- `Crypt.public_key_from_hex` now raises `ArgumentError` on an invalid key, rather than an `OpenSSL::PKey::EC::Point::Error`.
|
|
15
|
+
- Explicitly require 'stringio' (thanks thekuwayama!).
|
|
16
|
+
|
|
17
|
+
0.3.0
|
|
18
|
+
---
|
|
19
|
+
Released on 2018-04-22
|
|
20
|
+
|
|
21
|
+
- Prevent benign malleability, as suggested in sec1-v2 page 97.
|
|
22
|
+
- The ECIES process is modified to prevent benign malleability by including the ephemeral public key as an input to the KDF.
|
|
23
|
+
- All encrypted output generated with previous versions cannot be decrypted with this version, and older versions cannot decrypt output generated with this version.
|
|
24
|
+
- The choice was made to simply break compatibility early in this library's life, rather than add an extra configuration parameter that should almost always be unused.
|
|
25
|
+
- Add `Crypt.public_key_from_hex` method.
|
|
26
|
+
- Add `Crypt.private_key_from_hex` method.
|
|
27
|
+
- Remove support for hex-encoded keys in `Crypt#encrypt` and `Crypt#decrypt` methods. The above `*_from_hex` helper methods can be used instead.
|
|
28
|
+
- Remove `ec_group` option from `Crypt` constructor.
|
|
29
|
+
- Add `Crypt#to_s` method.
|
|
30
|
+
|
|
7
31
|
0.2.0
|
|
8
32
|
---
|
|
9
|
-
|
|
33
|
+
Released on 2018-04-19
|
|
10
34
|
|
|
11
35
|
- Add support for hex-encoded keys in `Crypt#encrypt` and `Crypt#decrypt` methods.
|
|
12
36
|
- Add new option `ec_group` in `Crypt` constructor.
|
data/README.md
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
# ECIES - Elliptical Curve Integrated Encryption System
|
|
2
2
|
|
|
3
|
-
[](https://travis-ci.org/jamoes/ecies)
|
|
4
|
-
|
|
5
3
|
## Description
|
|
6
4
|
|
|
7
5
|
This library implements Elliptical Curve Integrated Encryption System (ECIES), as specified by [SEC 1: Elliptic Curve Cryptography, Version 2.0](http://www.secg.org/sec1-v2.pdf).
|
|
8
6
|
|
|
9
7
|
ECIES is a public-key encryption scheme based on ECC. It is designed to be semantically secure in the presence of an adversary capable of launching chosen-plaintext and chosen-ciphertext attacks.
|
|
10
8
|
|
|
11
|
-
ECIES can be used to encrypt messages to bitcoin addresses with keys published on the blockchain, and subsequently to decrypt messages by the holders of the address's private key.
|
|
9
|
+
ECIES can be used to encrypt messages to bitcoin addresses with public keys published on the blockchain, and subsequently to decrypt messages by the holders of the address's private key.
|
|
12
10
|
|
|
13
11
|
## Installation
|
|
14
12
|
|
|
@@ -27,7 +25,7 @@ require 'ecies'
|
|
|
27
25
|
Intitlialize a key and a `Crypt` object.
|
|
28
26
|
|
|
29
27
|
```ruby
|
|
30
|
-
key = OpenSSL::PKey::EC.
|
|
28
|
+
key = OpenSSL::PKey::EC.generate('secp256k1')
|
|
31
29
|
crypt = ECIES::Crypt.new
|
|
32
30
|
```
|
|
33
31
|
|
|
@@ -48,17 +46,17 @@ crypt.decrypt(key, encrypted) # => "secret message"
|
|
|
48
46
|
Bitcoin P2PKH addresses themselves contain only *hashes* of public keys (hence the name, pay-to-public-key-hash). However, any time a P2PKH output is spent, the public key associated with the address is published on the blockchain in the transaction's scriptSig. This allows you to encrypt a message to any bitcoin address that has sent a transaction (or published its public key in other ways). To demonstrate this, we'll encrypt a message to Satoshi's public key from Bitcoin's genesis block:
|
|
49
47
|
|
|
50
48
|
```ruby
|
|
51
|
-
|
|
49
|
+
public_key = ECIES::Crypt.public_key_from_hex(
|
|
52
50
|
"04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb"\
|
|
53
|
-
"649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"
|
|
54
|
-
encrypted = ECIES::Crypt.new.encrypt(
|
|
51
|
+
"649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f")
|
|
52
|
+
encrypted = ECIES::Crypt.new.encrypt(public_key, 'secret message')
|
|
55
53
|
```
|
|
56
54
|
|
|
57
55
|
To decrypt this message, Satoshi would follow these steps:
|
|
58
56
|
|
|
59
57
|
```ruby
|
|
60
|
-
|
|
61
|
-
ECIES::Crypt.new.decrypt(
|
|
58
|
+
private_key = OpenSSL::PKey::EC.new("<PEM/DER encoded private key for genesis block>")
|
|
59
|
+
ECIES::Crypt.new.decrypt(private_key, encrypted) # => "secret message"
|
|
62
60
|
```
|
|
63
61
|
|
|
64
62
|
### Default parameters
|
|
@@ -74,8 +72,7 @@ These defaults work well for encrypting messages to bitcoin keys. This library a
|
|
|
74
72
|
|
|
75
73
|
## Compatibility
|
|
76
74
|
|
|
77
|
-
The sec1-v2 document allows for
|
|
78
|
-
|
|
75
|
+
The sec1-v2 document allows for many combinations of various algorithms for ECIES. This library only supports a subset of the allowable algorithms:
|
|
79
76
|
- Key Derivation Functions
|
|
80
77
|
- Supported:
|
|
81
78
|
- ANSI-X9.63-KDF
|
|
@@ -119,6 +116,10 @@ The sec1-v2 document allows for a many combinations of various algorithms for EC
|
|
|
119
116
|
- 3-key TDES in CBC mode
|
|
120
117
|
- XOR encryption scheme
|
|
121
118
|
|
|
119
|
+
In addition, the following options have been chosen:
|
|
120
|
+
- Elliptical curve points are represented in compressed form.
|
|
121
|
+
- Benign malleability is prevented by including the ephemeral public key as an input to the KDF (sec1-v2 p97).
|
|
122
|
+
|
|
122
123
|
## Supported platforms
|
|
123
124
|
|
|
124
125
|
Ruby 2.0 and above.
|
data/certs/jamoes.pem
CHANGED
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
-----BEGIN CERTIFICATE-----
|
|
2
|
-
|
|
2
|
+
MIIEeDCCAuCgAwIBAgIBATANBgkqhkiG9w0BAQsFADBBMRMwEQYDVQQDDApzam1j
|
|
3
3
|
Y2FydGh5MRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZFgNj
|
|
4
|
-
|
|
4
|
+
b20wHhcNMjMwNjIwMjEwMTI2WhcNMjQwNjE5MjEwMTI2WjBBMRMwEQYDVQQDDApz
|
|
5
5
|
am1jY2FydGh5MRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZ
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
6
|
+
FgNjb20wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDOGmdomo9zQxUD
|
|
7
|
+
PMEtDYtzY7Fnb/T/TVXAhKMO06Fw84eEMdU4yOUOMapsv6DinBMm0kDjseFkuqm+
|
|
8
|
+
BFYcU7AaGfKOuoPJQ23LuQOBXg5STw+pDKGdoq1th26M1v05Q9hCH4HVlGIiNPzx
|
|
9
|
+
J+0jFoH9qmiNhHxCD03702etb/ppJsCbBGzpMzofbgKQEHIKZNAkVi2RU2QLqXDt
|
|
10
|
+
A44wknz8NkiWahgN24cpLn/euz5G+J4nFgJ32YUBgA/mVXdeEOhxgMCPIbHIxiez
|
|
11
|
+
3c/yymARogxf6e9b3Pcwo1k63zTZYf9YHIM+Q5lKiOWOGQ1lUG3nanB9NhFdUkAk
|
|
12
|
+
PcuEzQUp5/pQmnoM/j+VpeXyvwiNLTzsxNRGfePSZU+oDpkEvlN1qaJXmHRpedWp
|
|
13
|
+
zOcUlVUpwFSWM1WWDGm4FCxoYH8GdYdHVXmUWWm/iPcfLCkXwNUXL+i38OXbVSp2
|
|
14
|
+
aqaXrRtkwZsfmE4PCHVUJyHFeVXLqvgK3DLVPfCGk6ty4X7wuXcCAwEAAaN7MHkw
|
|
15
|
+
CQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFELj2NEPT2elfT1kefaM
|
|
16
|
+
tcBz+k6QMB8GA1UdEQQYMBaBFHNqbWNjYXJ0aHlAZ21haWwuY29tMB8GA1UdEgQY
|
|
17
|
+
MBaBFHNqbWNjYXJ0aHlAZ21haWwuY29tMA0GCSqGSIb3DQEBCwUAA4IBgQBvbFzT
|
|
18
|
+
zHTVmJ2J3VvWf1J4HFTkLDtRi9lFLtPqvsNczd+FeO3s/pI9/gr56mBgpZ/vLypN
|
|
19
|
+
9CBkk4wR4GLifl8+xuDtVkYYh3Ru9S3ru8iu225aOIfg6MpKH7x+IsShxm7jdEva
|
|
20
|
+
AnqMQ47KEOdRetbBMIHeWtCSxyKhXSJsfoIh+fkQZlIM6+3l0ljTiRxo5Eb1JyEn
|
|
21
|
+
Wb+jyVwJugHuGPb2tB9dx+khKgrv0YQ0lxsIaqSYRT5pb3xZuJNoxj00IsZGOx0J
|
|
22
|
+
s5SzopHnmHWPS0h9CVcTa9QgEz5MbCk1X2rWhmUkGR0pzHdeq6vvWr0pxhpiWJdA
|
|
23
|
+
eaD1Uldg06Zi31RbAARghTuRKzg+SA9/DmglkO479GuEhZvGA0P2fBvKTaVAZR+4
|
|
24
|
+
Lb3ESftZmM+MReXZS5FfAeYJBG5+R/LDyMiuQIz6WLYcPpfHpSX873IXAcNYTCd4
|
|
25
|
+
RVHpiTyCFYjchqoOvSC7rHgf1HpEQbuXsl9RKWhSQOyTGlUGbCCGFDx10Dg=
|
|
26
|
+
-----END CERTIFICATE-----
|
data/ecies.gemspec
CHANGED
|
@@ -14,17 +14,14 @@ Gem::Specification.new do |s|
|
|
|
14
14
|
s.homepage = 'https://github.com/jamoes/ecies'
|
|
15
15
|
s.license = 'MIT'
|
|
16
16
|
|
|
17
|
-
s.cert_chain = ['certs/jamoes.pem']
|
|
18
|
-
s.signing_key = File.expand_path("~/.ssh/gem-private_key.pem") if $0 =~ /gem\z/
|
|
19
|
-
|
|
20
17
|
s.files = `git ls-files`.split("\n")
|
|
21
18
|
s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
|
22
19
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
|
23
20
|
|
|
24
21
|
s.required_ruby_version = '>= 2.0'
|
|
25
22
|
|
|
26
|
-
s.add_development_dependency 'bundler', '~>
|
|
27
|
-
s.add_development_dependency 'rake', '~>
|
|
23
|
+
s.add_development_dependency 'bundler', '~> 2'
|
|
24
|
+
s.add_development_dependency 'rake', '~> 13'
|
|
28
25
|
s.add_development_dependency 'rspec', '~> 3.7'
|
|
29
26
|
s.add_development_dependency 'simplecov', '~> 0'
|
|
30
27
|
s.add_development_dependency 'yard', '~> 0.9.12'
|
data/lib/ecies/crypt.rb
CHANGED
|
@@ -27,9 +27,6 @@ module ECIES
|
|
|
27
27
|
# length will be equal to half the mac_digest's digest_legnth. If
|
|
28
28
|
# :full, the mac length will be equal to the mac_digest's
|
|
29
29
|
# digest_length.
|
|
30
|
-
# @param ec_group [OpenSSL::PKey::EC::Group,String] The elliptical curve
|
|
31
|
-
# group to use when the key is passed in hex form to `encrypt` or
|
|
32
|
-
# `decrypt`.
|
|
33
30
|
# @param kdf_digest [String,OpenSSL::Digest,nil] The digest algorithm to
|
|
34
31
|
# use for KDF. If not specified, the `digest` argument will be used.
|
|
35
32
|
# @param mac_digest [String,OpenSSL::Digest,nil] The digest algorithm to
|
|
@@ -38,9 +35,8 @@ module ECIES
|
|
|
38
35
|
# info used for KDF, also known as SharedInfo1.
|
|
39
36
|
# @param mac_shared_info [String] Optional. A string containing the shared
|
|
40
37
|
# info used for MAC, also known as SharedInfo2.
|
|
41
|
-
def initialize(cipher: 'AES-256-CTR', digest: 'SHA256', mac_length: :half,
|
|
38
|
+
def initialize(cipher: 'AES-256-CTR', digest: 'SHA256', mac_length: :half, kdf_digest: nil, mac_digest: nil, kdf_shared_info: '', mac_shared_info: '')
|
|
42
39
|
@cipher = OpenSSL::Cipher.new(cipher)
|
|
43
|
-
@ec_group = OpenSSL::PKey::EC::Group.new(ec_group)
|
|
44
40
|
@mac_digest = OpenSSL::Digest.new(mac_digest || digest)
|
|
45
41
|
@kdf_digest = OpenSSL::Digest.new(kdf_digest || digest)
|
|
46
42
|
@kdf_shared_info = kdf_shared_info
|
|
@@ -57,27 +53,19 @@ module ECIES
|
|
|
57
53
|
|
|
58
54
|
# Encrypts a message to a public key using ECIES.
|
|
59
55
|
#
|
|
60
|
-
# @param key [OpenSSL::EC:PKey
|
|
61
|
-
# containing the public key, or a hex-encoded string representing the
|
|
62
|
-
# public key on this Crypt's `ec_group`.
|
|
56
|
+
# @param key [OpenSSL::EC:PKey] The public key.
|
|
63
57
|
# @param message [String] The plain-text message.
|
|
64
58
|
# @return [String] The octet string of the encrypted message.
|
|
65
59
|
def encrypt(key, message)
|
|
66
|
-
if key.is_a?(String)
|
|
67
|
-
new_key = OpenSSL::PKey::EC.new(@ec_group)
|
|
68
|
-
new_key.public_key = OpenSSL::PKey::EC::Point.new(@ec_group, OpenSSL::BN.new(key, 16))
|
|
69
|
-
key = new_key
|
|
70
|
-
end
|
|
71
60
|
key.public_key? or raise "Must have public key to encrypt"
|
|
72
61
|
@cipher.reset
|
|
73
62
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
ephemeral_key = OpenSSL::PKey::EC.new(group_copy).generate_key
|
|
63
|
+
ephemeral_key = OpenSSL::PKey::EC.generate(key.group)
|
|
64
|
+
ephemeral_public_key_octet = ephemeral_key.public_key.to_octet_string(:compressed)
|
|
77
65
|
|
|
78
66
|
shared_secret = ephemeral_key.dh_compute_key(key.public_key)
|
|
79
67
|
|
|
80
|
-
key_pair = kdf(shared_secret, @cipher.key_len + @mac_length)
|
|
68
|
+
key_pair = kdf(shared_secret, @cipher.key_len + @mac_length, ephemeral_public_key_octet)
|
|
81
69
|
cipher_key = key_pair.byteslice(0, @cipher.key_len)
|
|
82
70
|
hmac_key = key_pair.byteslice(-@mac_length, @mac_length)
|
|
83
71
|
|
|
@@ -88,42 +76,31 @@ module ECIES
|
|
|
88
76
|
|
|
89
77
|
mac = OpenSSL::HMAC.digest(@mac_digest, hmac_key, ciphertext + @mac_shared_info).byteslice(0, @mac_length)
|
|
90
78
|
|
|
91
|
-
|
|
79
|
+
ephemeral_public_key_octet + ciphertext + mac
|
|
92
80
|
end
|
|
93
81
|
|
|
94
82
|
# Decrypts a message with a private key using ECIES.
|
|
95
83
|
#
|
|
96
84
|
# @param key [OpenSSL::EC:PKey] The private key.
|
|
97
|
-
# @param key [OpenSSL::EC:PKey,String] The private key. An OpenSSL::EC:PKey
|
|
98
|
-
# containing the private key, or a hex-encoded string representing the
|
|
99
|
-
# private key on this Crypt's `ec_group`.
|
|
100
85
|
# @param encrypted_message [String] Octet string of the encrypted message.
|
|
101
86
|
# @return [String] The plain-text message.
|
|
102
87
|
def decrypt(key, encrypted_message)
|
|
103
|
-
if key.is_a?(String)
|
|
104
|
-
new_key = OpenSSL::PKey::EC.new(@ec_group)
|
|
105
|
-
new_key.private_key = OpenSSL::BN.new(key, 16)
|
|
106
|
-
key = new_key
|
|
107
|
-
end
|
|
108
88
|
key.private_key? or raise "Must have private key to decrypt"
|
|
109
89
|
@cipher.reset
|
|
110
90
|
|
|
111
|
-
|
|
112
|
-
group_copy.point_conversion_form = :compressed
|
|
113
|
-
|
|
114
|
-
ephemeral_public_key_length = group_copy.generator.to_bn.to_s(2).bytesize
|
|
91
|
+
ephemeral_public_key_length = key.group.generator.to_octet_string(:compressed).bytesize
|
|
115
92
|
ciphertext_length = encrypted_message.bytesize - ephemeral_public_key_length - @mac_length
|
|
116
93
|
ciphertext_length > 0 or raise OpenSSL::PKey::ECError, "Encrypted message too short"
|
|
117
94
|
|
|
118
|
-
|
|
95
|
+
ephemeral_public_key_octet = encrypted_message.byteslice(0, ephemeral_public_key_length)
|
|
119
96
|
ciphertext = encrypted_message.byteslice(ephemeral_public_key_length, ciphertext_length)
|
|
120
97
|
mac = encrypted_message.byteslice(-@mac_length, @mac_length)
|
|
121
98
|
|
|
122
|
-
ephemeral_public_key = OpenSSL::PKey::EC::Point.new(
|
|
99
|
+
ephemeral_public_key = OpenSSL::PKey::EC::Point.new(key.group, OpenSSL::BN.new(ephemeral_public_key_octet, 2))
|
|
123
100
|
|
|
124
101
|
shared_secret = key.dh_compute_key(ephemeral_public_key)
|
|
125
102
|
|
|
126
|
-
key_pair = kdf(shared_secret, @cipher.key_len + @mac_length)
|
|
103
|
+
key_pair = kdf(shared_secret, @cipher.key_len + @mac_length, ephemeral_public_key_octet)
|
|
127
104
|
cipher_key = key_pair.byteslice(0, @cipher.key_len)
|
|
128
105
|
hmac_key = key_pair.byteslice(-@mac_length, @mac_length)
|
|
129
106
|
|
|
@@ -139,11 +116,13 @@ module ECIES
|
|
|
139
116
|
|
|
140
117
|
# Key-derivation function, compatible with ANSI-X9.63-KDF
|
|
141
118
|
#
|
|
142
|
-
# @param shared_secret [String] The shared secret from which the key will
|
|
143
|
-
# derived.
|
|
119
|
+
# @param shared_secret [String] The shared secret from which the key will
|
|
120
|
+
# be derived.
|
|
144
121
|
# @param length [Integer] The length of the key to generate.
|
|
122
|
+
# @param shared_info_suffix [String] The suffix to append to the
|
|
123
|
+
# shared_info.
|
|
145
124
|
# @return [String] Octet string of the derived key.
|
|
146
|
-
def kdf(shared_secret, length)
|
|
125
|
+
def kdf(shared_secret, length, shared_info_suffix)
|
|
147
126
|
length >=0 or raise "length cannot be negative"
|
|
148
127
|
return "" if length == 0
|
|
149
128
|
|
|
@@ -158,11 +137,39 @@ module ECIES
|
|
|
158
137
|
counter += 1
|
|
159
138
|
counter_bytes = [counter].pack('N')
|
|
160
139
|
|
|
161
|
-
io << @kdf_digest.digest(shared_secret + counter_bytes + @kdf_shared_info)
|
|
140
|
+
io << @kdf_digest.digest(shared_secret + counter_bytes + @kdf_shared_info + shared_info_suffix)
|
|
162
141
|
if io.pos >= length
|
|
163
142
|
return io.string.byteslice(0, length)
|
|
164
143
|
end
|
|
165
144
|
end
|
|
166
145
|
end
|
|
146
|
+
|
|
147
|
+
# @return [String] A string representing this Crypt's parameters.
|
|
148
|
+
def to_s
|
|
149
|
+
"KDF-#{@kdf_digest.name}_" +
|
|
150
|
+
"HMAC-SHA-#{@mac_digest.digest_length * 8}-#{@mac_length * 8}_" +
|
|
151
|
+
@cipher.name
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Converts a hex-encoded public key to an `OpenSSL::PKey::EC`.
|
|
155
|
+
#
|
|
156
|
+
# @param hex_string [String] The hex-encoded public key.
|
|
157
|
+
# @param ec_group [OpenSSL::PKey::EC::Group,String] The elliptical curve
|
|
158
|
+
# group for this public key.
|
|
159
|
+
# @return [OpenSSL::PKey::EC] The public key.
|
|
160
|
+
# @raise [ArgumentError] If the public key is invalid.
|
|
161
|
+
def self.public_key_from_hex(hex_string, ec_group = 'secp256k1')
|
|
162
|
+
ec_group = OpenSSL::PKey::EC::Group.new(ec_group) if ec_group.is_a?(String)
|
|
163
|
+
|
|
164
|
+
sequence = OpenSSL::ASN1.Sequence([
|
|
165
|
+
OpenSSL::ASN1.Sequence([
|
|
166
|
+
OpenSSL::ASN1.ObjectId("id-ecPublicKey"),
|
|
167
|
+
OpenSSL::ASN1::ObjectId(ec_group.curve_name),
|
|
168
|
+
]),
|
|
169
|
+
OpenSSL::ASN1.BitString([hex_string].pack('H*')),
|
|
170
|
+
])
|
|
171
|
+
|
|
172
|
+
OpenSSL::PKey::EC.new(sequence.to_der)
|
|
173
|
+
end
|
|
167
174
|
end
|
|
168
175
|
end
|
data/lib/ecies/version.rb
CHANGED
data/lib/ecies.rb
CHANGED
data/spec/crypt_spec.rb
CHANGED
|
@@ -5,89 +5,79 @@ describe ECIES::Crypt do
|
|
|
5
5
|
describe 'Encryption and decryption' do
|
|
6
6
|
|
|
7
7
|
it 'Encrypts and decrypts' do
|
|
8
|
-
key = OpenSSL::PKey::EC.
|
|
8
|
+
key = OpenSSL::PKey::EC.generate('secp256k1')
|
|
9
9
|
crypt = ECIES::Crypt.new
|
|
10
10
|
|
|
11
11
|
encrypted = crypt.encrypt(key, 'secret')
|
|
12
12
|
expect(crypt.decrypt(key, encrypted)).to eq 'secret'
|
|
13
|
+
|
|
14
|
+
expect{ ECIES::Crypt.new(mac_length: :full).decrypt(key, encrypted) }.to raise_error(OpenSSL::PKey::ECError)
|
|
15
|
+
expect{ ECIES::Crypt.new(mac_digest: 'sha512').decrypt(key, encrypted) }.to raise_error(OpenSSL::PKey::ECError)
|
|
13
16
|
end
|
|
14
17
|
|
|
15
18
|
it 'Supports hex-encoded keys' do
|
|
16
|
-
key = OpenSSL::PKey::EC.
|
|
19
|
+
key = OpenSSL::PKey::EC.generate('secp256k1')
|
|
17
20
|
public_key_hex = key.public_key.to_bn.to_s(16)
|
|
18
|
-
private_key_hex = key.private_key.to_s(16)
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
public_key = ECIES::Crypt.public_key_from_hex(public_key_hex)
|
|
23
|
+
|
|
24
|
+
expect(public_key.public_key).to eq key.public_key
|
|
21
25
|
|
|
22
|
-
|
|
23
|
-
expect(crypt.decrypt(private_key_hex, encrypted)).to eq 'secret'
|
|
26
|
+
expect{ ECIES::Crypt.public_key_from_hex(public_key_hex, 'secp224k1') }.to raise_error(ArgumentError)
|
|
24
27
|
end
|
|
25
28
|
|
|
26
29
|
it 'Supports other EC curves' do
|
|
27
|
-
key = OpenSSL::PKey::EC.
|
|
28
|
-
crypt = ECIES::Crypt.new
|
|
30
|
+
key = OpenSSL::PKey::EC.generate('secp224k1')
|
|
31
|
+
crypt = ECIES::Crypt.new
|
|
29
32
|
|
|
30
33
|
encrypted = crypt.encrypt(key, 'secret')
|
|
31
34
|
expect(crypt.decrypt(key, encrypted)).to eq 'secret'
|
|
32
|
-
|
|
33
|
-
encrypted = crypt.encrypt(key.public_key.to_bn.to_s(16), 'secret')
|
|
34
|
-
expect(crypt.decrypt(key.private_key.to_s(16), encrypted)).to eq 'secret'
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
context 'known value' do
|
|
38
|
+
before(:all) do
|
|
39
|
+
OpenSSL::PKey::EC.instance_eval do
|
|
40
|
+
# Overwrites `generate` for both the key generated below, and the
|
|
41
|
+
# ephemeral_key generated in the `encrypt` method.
|
|
42
|
+
# The private_key is equal to '2', and the group is 'secp256k1'.
|
|
43
|
+
def generate(group)
|
|
44
|
+
OpenSSL::PKey::EC.new("0t\x02\x01\x01\x04 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xA0\a\x06\x05+\x81\x04\x00\n\xA1D\x03B\x00\x04\xC6\x04\x7F\x94A\xED}m0E@n\x95\xC0|\xD8\\w\x8EK\x8C\xEF<\xA7\xAB\xAC\t\xB9\\p\x9E\xE5\x1A\xE1h\xFE\xA6=\xC39\xA3\xC5\x84\x19Fl\xEA\xEE\xF7\xF62e2f\xD0\xE1#d1\xA9P\xCF\xE5*")
|
|
45
|
+
end
|
|
46
|
+
end
|
|
40
47
|
|
|
41
|
-
|
|
42
|
-
|
|
48
|
+
@key = OpenSSL::PKey::EC.generate('secp256k1')
|
|
49
|
+
end
|
|
43
50
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
[
|
|
52
|
+
[ECIES::Crypt.new, "\x02\xC6\x04\x7F\x94A\xED}m0E@n\x95\xC0|\xD8\\w\x8EK\x8C\xEF<\xA7\xAB\xAC\t\xB9\\p\x9E\xE5C\x9E\xE0\x0FYBZ\xBB\xC8\x95\x93\xC1@\xC6+\xE2/yb\x065\xFF".b],
|
|
53
|
+
[ECIES::Crypt.new(mac_length: :full), "\x02\xC6\x04\x7F\x94A\xED}m0E@n\x95\xC0|\xD8\\w\x8EK\x8C\xEF<\xA7\xAB\xAC\t\xB9\\p\x9E\xE5C\x9E\xE0\x0FYB\x03.\x1E\x92,[\rI\xBC\xCC\xFD%\xCD)9\v!]]A\xE0\xADc\xBA[\xA4\xF2\xB1\xB5\xC5)\xA4".b],
|
|
54
|
+
[ECIES::Crypt.new(digest: 'sha512', mac_length: :full), "\x02\xC6\x04\x7F\x94A\xED}m0E@n\x95\xC0|\xD8\\w\x8EK\x8C\xEF<\xA7\xAB\xAC\t\xB9\\p\x9E\xE5\xA2Y\x1A\x7F\xB3\xB2\xA7\xDE\x03\xF4\xA6\e\xD1\x9F\xF9\xD5P\x06\x91\x8EiW\xC82\xD9\xBB\xD2\xC92\xE2\x9F\x15F.\x8C]\xE3Y2\xD3L\xE8\xC4\x9F\xBF\xA5S\x98\x9AYy_Y\xF8\x05\xE7\x19\x9E\xDA\vn;Bvm\xA2`i5:".b],
|
|
55
|
+
[ECIES::Crypt.new(cipher: 'aes-256-cbc', mac_length: :full), "\x02\xC6\x04\x7F\x94A\xED}m0E@n\x95\xC0|\xD8\\w\x8EK\x8C\xEF<\xA7\xAB\xAC\t\xB9\\p\x9E\xE5\xDF\xCD\x95\xAD!m\xAA/Xv\"\x97\x04\xEE\x9F\xEB^\x1F\xA7\xC9n\xE3\x94l;\xBA\xF2\xBE\xCD\x83\x02+\x02\x9D\x18\x11\x9A\xBEz_\x8A\xDB\xA3\x00\xF7\x8A\x94G".b],
|
|
56
|
+
[ECIES::Crypt.new(mac_digest: 'sha256', kdf_digest: 'sha512'), "\x02\xC6\x04\x7F\x94A\xED}m0E@n\x95\xC0|\xD8\\w\x8EK\x8C\xEF<\xA7\xAB\xAC\t\xB9\\p\x9E\xE5\xA2Y\x1A\x7F\xB3\xB2l\x9E|\xC4\xBCE r\xA6\xB1k\x93W\xE5d\xE4".b],
|
|
57
|
+
].each do |crypt, expected_value|
|
|
58
|
+
it "matches for #{crypt.to_s}" do
|
|
59
|
+
encrypted = crypt.encrypt(@key, 'secret')
|
|
60
|
+
expect(encrypted).to eq expected_value
|
|
61
|
+
expect(crypt.decrypt(@key, encrypted)).to eq 'secret'
|
|
52
62
|
end
|
|
53
63
|
end
|
|
64
|
+
end
|
|
54
65
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
expect{ crypt_full.decrypt(key, encrypted) }.to raise_error(OpenSSL::PKey::ECError)
|
|
67
|
-
|
|
68
|
-
encrypted = crypt_full.encrypt(key, 'secret')
|
|
69
|
-
expect(encrypted).to eq "\x02\xC6\x04\x7F\x94A\xED}m0E@n\x95\xC0|\xD8\\w\x8EK\x8C\xEF<\xA7\xAB\xAC\t\xB9\\p\x9E\xE5B;\x12:\x17\xCEo\x9B\xA7\x955\x89\x9FR\xDF\x1C\xED\x00\x86<\n\x04\v\xD6(\x9D\xF5\xF9\x13\xC8/\xD7os(ZsF".force_encoding(Encoding::BINARY)
|
|
70
|
-
expect(crypt_full.decrypt(key, encrypted)).to eq 'secret'
|
|
71
|
-
expect{ crypt_sha512.decrypt(key, encrypted) }.to raise_error(OpenSSL::PKey::ECError)
|
|
72
|
-
|
|
73
|
-
encrypted = crypt_sha512.encrypt(key, 'secret')
|
|
74
|
-
expect(encrypted).to eq "\x02\xC6\x04\x7F\x94A\xED}m0E@n\x95\xC0|\xD8\\w\x8EK\x8C\xEF<\xA7\xAB\xAC\t\xB9\\p\x9E\xE5%\r^\xA9\xD9\xDC\xFB\xD7\x14b\xB4\x00\x84\xABl\xEAh\x0Fc\x805\xAF\x1DT\x05\x87`\xA5\xC4\xB7\xB5r\xF6\x89\xB1U0\x0E \xD4\x1E\x16\x184\xE9:\xE7\x951\xF4\xB3\x93\"A\x85\x1F\x9A\x8E\xAD\xE1(\x1D\xB3\xC4\x15\xD3\xB1\xA8\xFB\x1D".force_encoding(Encoding::BINARY)
|
|
75
|
-
expect(crypt_sha512.decrypt(key, encrypted)).to eq 'secret'
|
|
76
|
-
expect{ crypt_full.decrypt(key, encrypted) }.to raise_error(OpenSSL::PKey::ECError)
|
|
77
|
-
|
|
78
|
-
encrypted = crypt_cbc.encrypt(key, 'secret')
|
|
79
|
-
expect(encrypted).to eq "\x02\xC6\x04\x7F\x94A\xED}m0E@n\x95\xC0|\xD8\\w\x8EK\x8C\xEF<\xA7\xAB\xAC\t\xB9\\p\x9E\xE5\x1Fj\x04N\eg($\xD4\xFBD\xFFd\xA1\xA3z\x90T#\x1D\x12{3IM\x93!|\xA5\xAF&\xD4+;\e\xA6i.wD\x1F\xCB\xE1\x90{\xB6\x8B\xAF".force_encoding(Encoding::BINARY)
|
|
80
|
-
expect(crypt_cbc.decrypt(key, encrypted)).to eq 'secret'
|
|
81
|
-
expect{ crypt_mixed.decrypt(key, encrypted) }.to raise_error(OpenSSL::PKey::ECError)
|
|
82
|
-
|
|
83
|
-
encrypted = crypt_mixed.encrypt(key, 'secret')
|
|
84
|
-
expect(encrypted).to eq "\x02\xC6\x04\x7F\x94A\xED}m0E@n\x95\xC0|\xD8\\w\x8EK\x8C\xEF<\xA7\xAB\xAC\t\xB9\\p\x9E\xE5%\r^\xA9\xD9\xDC\xF5\\\x9A\x04\xE0T\x91\xEA=\xA6W\x84X\xBB\xCA\xB4".force_encoding(Encoding::BINARY)
|
|
85
|
-
expect(crypt_mixed.decrypt(key, encrypted)).to eq 'secret'
|
|
86
|
-
expect{ crypt_full.decrypt(key, encrypted) }.to raise_error(OpenSSL::PKey::ECError)
|
|
66
|
+
it '#to_s' do
|
|
67
|
+
[
|
|
68
|
+
[ECIES::Crypt.new, "KDF-SHA256_HMAC-SHA-256-128_AES-256-CTR"],
|
|
69
|
+
[ECIES::Crypt.new(mac_length: :full), "KDF-SHA256_HMAC-SHA-256-256_AES-256-CTR"],
|
|
70
|
+
[ECIES::Crypt.new(digest: 'sha512'), "KDF-SHA512_HMAC-SHA-512-256_AES-256-CTR"],
|
|
71
|
+
[ECIES::Crypt.new(mac_digest: 'sha512'), "KDF-SHA256_HMAC-SHA-512-256_AES-256-CTR"],
|
|
72
|
+
[ECIES::Crypt.new(mac_digest: 'sha512', kdf_digest: 'sha224'), "KDF-SHA224_HMAC-SHA-512-256_AES-256-CTR"],
|
|
73
|
+
[ECIES::Crypt.new(cipher: 'aes-128-cbc'), "KDF-SHA256_HMAC-SHA-256-128_AES-128-CBC"],
|
|
74
|
+
].each do |crypt, expected_value|
|
|
75
|
+
expect(crypt.to_s).to eq expected_value
|
|
76
|
+
end
|
|
87
77
|
end
|
|
88
78
|
|
|
89
79
|
it 'Raises on unknown cipher or digest' do
|
|
90
|
-
key = OpenSSL::PKey::EC.
|
|
80
|
+
key = OpenSSL::PKey::EC.generate('secp256k1')
|
|
91
81
|
|
|
92
82
|
expect{ ECIES::Crypt.new(digest: 'foo') }.to raise_error(RuntimeError)
|
|
93
83
|
expect{ ECIES::Crypt.new(digest: 'md5') }.to raise_error(RuntimeError)
|
|
@@ -103,10 +93,8 @@ describe ECIES::Crypt do
|
|
|
103
93
|
end
|
|
104
94
|
end
|
|
105
95
|
|
|
106
|
-
|
|
107
|
-
|
|
108
96
|
describe '#kdf' do
|
|
109
|
-
it '
|
|
97
|
+
it 'derives keys correctly' do
|
|
110
98
|
sha256_test_vectors = [
|
|
111
99
|
# [shared_secret, shared_info, expected_key]
|
|
112
100
|
['96c05619d56c328ab95fe84b18264b08725b85e33fd34f08', '', '443024c3dae66b95e6f5670601558f71'],
|
|
@@ -120,16 +108,24 @@ describe ECIES::Crypt do
|
|
|
120
108
|
shared_info = [shared_info].pack('H*')
|
|
121
109
|
expected_key = [expected_key].pack('H*')
|
|
122
110
|
|
|
123
|
-
computed_key = ECIES::Crypt.new(kdf_shared_info: shared_info).kdf(shared_secret, expected_key.size)
|
|
124
|
-
|
|
111
|
+
computed_key = ECIES::Crypt.new(kdf_shared_info: shared_info).kdf(shared_secret, expected_key.size, '')
|
|
125
112
|
expect(computed_key).to eq expected_key
|
|
126
113
|
end
|
|
127
114
|
end
|
|
128
115
|
|
|
116
|
+
it 'concats kdf_shared_info with shared_info_suffix' do
|
|
117
|
+
shared_secret = ['22518b10e70f2a3f243810ae3254139efbee04aa57c7af7d'].pack('H*')
|
|
118
|
+
shared_info = ['75eef81aa3041e33'].pack('H*')
|
|
119
|
+
shared_info_suffix = ['b80971203d2c0c52'].pack('H*')
|
|
120
|
+
expected_key = ['c498af77161cc59f2962b9a713e2b215152d139766ce34a776df11866a69bf2e52a13d9c7c6fc878c50c5ea0bc7b00e0da2447cfd874f6cf92f30d0097111485500c90c3af8b487872d04685d14c8d1dc8d7fa08beb0ce0ababc11f0bd496269142d43525a78e5bc79a17f59676a5706dc54d54d4d1f0bd7e386128ec26afc21'].pack('H*')
|
|
121
|
+
|
|
122
|
+
computed_key = ECIES::Crypt.new(kdf_shared_info: shared_info).kdf(shared_secret, expected_key.size, shared_info_suffix)
|
|
123
|
+
expect(computed_key).to eq expected_key
|
|
124
|
+
end
|
|
125
|
+
|
|
129
126
|
it 'raises when size is invalid' do
|
|
130
|
-
expect{ ECIES::Crypt.new.kdf('a', -1) }.to raise_error(RuntimeError)
|
|
131
|
-
expect{ ECIES::Crypt.new.kdf('a', 32 * 2**32) }.to raise_error(RuntimeError)
|
|
127
|
+
expect{ ECIES::Crypt.new.kdf('a', -1, '') }.to raise_error(RuntimeError)
|
|
128
|
+
expect{ ECIES::Crypt.new.kdf('a', 32 * 2**32, '') }.to raise_error(RuntimeError)
|
|
132
129
|
end
|
|
133
130
|
end
|
|
134
|
-
|
|
135
131
|
end
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,36 +1,41 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ecies
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stephen McCarthy
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain:
|
|
11
11
|
- |
|
|
12
12
|
-----BEGIN CERTIFICATE-----
|
|
13
|
-
|
|
13
|
+
MIIEeDCCAuCgAwIBAgIBATANBgkqhkiG9w0BAQsFADBBMRMwEQYDVQQDDApzam1j
|
|
14
14
|
Y2FydGh5MRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZFgNj
|
|
15
|
-
|
|
15
|
+
b20wHhcNMjMwNjIwMjEwMTI2WhcNMjQwNjE5MjEwMTI2WjBBMRMwEQYDVQQDDApz
|
|
16
16
|
am1jY2FydGh5MRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZ
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
17
|
+
FgNjb20wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDOGmdomo9zQxUD
|
|
18
|
+
PMEtDYtzY7Fnb/T/TVXAhKMO06Fw84eEMdU4yOUOMapsv6DinBMm0kDjseFkuqm+
|
|
19
|
+
BFYcU7AaGfKOuoPJQ23LuQOBXg5STw+pDKGdoq1th26M1v05Q9hCH4HVlGIiNPzx
|
|
20
|
+
J+0jFoH9qmiNhHxCD03702etb/ppJsCbBGzpMzofbgKQEHIKZNAkVi2RU2QLqXDt
|
|
21
|
+
A44wknz8NkiWahgN24cpLn/euz5G+J4nFgJ32YUBgA/mVXdeEOhxgMCPIbHIxiez
|
|
22
|
+
3c/yymARogxf6e9b3Pcwo1k63zTZYf9YHIM+Q5lKiOWOGQ1lUG3nanB9NhFdUkAk
|
|
23
|
+
PcuEzQUp5/pQmnoM/j+VpeXyvwiNLTzsxNRGfePSZU+oDpkEvlN1qaJXmHRpedWp
|
|
24
|
+
zOcUlVUpwFSWM1WWDGm4FCxoYH8GdYdHVXmUWWm/iPcfLCkXwNUXL+i38OXbVSp2
|
|
25
|
+
aqaXrRtkwZsfmE4PCHVUJyHFeVXLqvgK3DLVPfCGk6ty4X7wuXcCAwEAAaN7MHkw
|
|
26
|
+
CQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFELj2NEPT2elfT1kefaM
|
|
27
|
+
tcBz+k6QMB8GA1UdEQQYMBaBFHNqbWNjYXJ0aHlAZ21haWwuY29tMB8GA1UdEgQY
|
|
28
|
+
MBaBFHNqbWNjYXJ0aHlAZ21haWwuY29tMA0GCSqGSIb3DQEBCwUAA4IBgQBvbFzT
|
|
29
|
+
zHTVmJ2J3VvWf1J4HFTkLDtRi9lFLtPqvsNczd+FeO3s/pI9/gr56mBgpZ/vLypN
|
|
30
|
+
9CBkk4wR4GLifl8+xuDtVkYYh3Ru9S3ru8iu225aOIfg6MpKH7x+IsShxm7jdEva
|
|
31
|
+
AnqMQ47KEOdRetbBMIHeWtCSxyKhXSJsfoIh+fkQZlIM6+3l0ljTiRxo5Eb1JyEn
|
|
32
|
+
Wb+jyVwJugHuGPb2tB9dx+khKgrv0YQ0lxsIaqSYRT5pb3xZuJNoxj00IsZGOx0J
|
|
33
|
+
s5SzopHnmHWPS0h9CVcTa9QgEz5MbCk1X2rWhmUkGR0pzHdeq6vvWr0pxhpiWJdA
|
|
34
|
+
eaD1Uldg06Zi31RbAARghTuRKzg+SA9/DmglkO479GuEhZvGA0P2fBvKTaVAZR+4
|
|
35
|
+
Lb3ESftZmM+MReXZS5FfAeYJBG5+R/LDyMiuQIz6WLYcPpfHpSX873IXAcNYTCd4
|
|
36
|
+
RVHpiTyCFYjchqoOvSC7rHgf1HpEQbuXsl9RKWhSQOyTGlUGbCCGFDx10Dg=
|
|
32
37
|
-----END CERTIFICATE-----
|
|
33
|
-
date:
|
|
38
|
+
date: 2023-06-20 00:00:00.000000000 Z
|
|
34
39
|
dependencies:
|
|
35
40
|
- !ruby/object:Gem::Dependency
|
|
36
41
|
name: bundler
|
|
@@ -38,28 +43,28 @@ dependencies:
|
|
|
38
43
|
requirements:
|
|
39
44
|
- - "~>"
|
|
40
45
|
- !ruby/object:Gem::Version
|
|
41
|
-
version: '
|
|
46
|
+
version: '2'
|
|
42
47
|
type: :development
|
|
43
48
|
prerelease: false
|
|
44
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
45
50
|
requirements:
|
|
46
51
|
- - "~>"
|
|
47
52
|
- !ruby/object:Gem::Version
|
|
48
|
-
version: '
|
|
53
|
+
version: '2'
|
|
49
54
|
- !ruby/object:Gem::Dependency
|
|
50
55
|
name: rake
|
|
51
56
|
requirement: !ruby/object:Gem::Requirement
|
|
52
57
|
requirements:
|
|
53
58
|
- - "~>"
|
|
54
59
|
- !ruby/object:Gem::Version
|
|
55
|
-
version: '
|
|
60
|
+
version: '13'
|
|
56
61
|
type: :development
|
|
57
62
|
prerelease: false
|
|
58
63
|
version_requirements: !ruby/object:Gem::Requirement
|
|
59
64
|
requirements:
|
|
60
65
|
- - "~>"
|
|
61
66
|
- !ruby/object:Gem::Version
|
|
62
|
-
version: '
|
|
67
|
+
version: '13'
|
|
63
68
|
- !ruby/object:Gem::Dependency
|
|
64
69
|
name: rspec
|
|
65
70
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -158,7 +163,7 @@ homepage: https://github.com/jamoes/ecies
|
|
|
158
163
|
licenses:
|
|
159
164
|
- MIT
|
|
160
165
|
metadata: {}
|
|
161
|
-
post_install_message:
|
|
166
|
+
post_install_message:
|
|
162
167
|
rdoc_options: []
|
|
163
168
|
require_paths:
|
|
164
169
|
- lib
|
|
@@ -173,9 +178,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
173
178
|
- !ruby/object:Gem::Version
|
|
174
179
|
version: '0'
|
|
175
180
|
requirements: []
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
signing_key:
|
|
181
|
+
rubygems_version: 3.3.25
|
|
182
|
+
signing_key:
|
|
179
183
|
specification_version: 4
|
|
180
184
|
summary: Elliptical Curve Integrated Encryption System (ECIES), as specified by SEC
|
|
181
185
|
1 - Ver. 2.0
|
metadata.gz.sig
CHANGED
|
Binary file
|