ecies 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/CHANGELOG.md +7 -0
- data/README.md +36 -5
- data/ecies.gemspec +5 -0
- data/lib/ecies/crypt.rb +21 -2
- data/lib/ecies/version.rb +1 -1
- data/spec/crypt_spec.rb +29 -0
- metadata +6 -3
- 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: b9b17b5e59affac68ce47a7afe053747c90c287201202fffe9a97550644d6c5c
|
4
|
+
data.tar.gz: 161fb791e8f8e67252ce565fa06fd1196228629e45b3ccbc07384b5b9f207a4a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df3185e4b726f977a8834c9718f0cbd9ffedec22f00ff597c7d7e877a1a730283b7d8ef66091a0351c3d5c71939cac60196b613a750c822d0d33e0b7d50b3d90
|
7
|
+
data.tar.gz: 148151802478d20abde87b33cfe0765bda7bf1714507c0e6c818105beeb57fcaf55f5735625c42f9cd7d8b524a09c2e5550b7d91c205e74830988c2f5718b503
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,13 @@ 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.2.0
|
8
|
+
---
|
9
|
+
Release 2018-04-19
|
10
|
+
|
11
|
+
- Add support for hex-encoded keys in `Crypt#encrypt` and `Crypt#decrypt` methods.
|
12
|
+
- Add new option `ec_group` in `Crypt` constructor.
|
13
|
+
|
7
14
|
0.1.0
|
8
15
|
----
|
9
16
|
Released on 2018-04-18
|
data/README.md
CHANGED
@@ -8,6 +8,8 @@ This library implements Elliptical Curve Integrated Encryption System (ECIES), a
|
|
8
8
|
|
9
9
|
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
10
|
|
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.
|
12
|
+
|
11
13
|
## Installation
|
12
14
|
|
13
15
|
This library is distributed as a gem named [ecies](https://rubygems.org/gems/ecies) at RubyGems.org. To install it, run:
|
@@ -38,16 +40,37 @@ encrypted = crypt.encrypt(key, 'secret message')
|
|
38
40
|
Finally, decrypt the message. In order to decrypt, the key must contain the private component.
|
39
41
|
|
40
42
|
```ruby
|
41
|
-
crypt.decrypt(key, encrypted) # =>
|
43
|
+
crypt.decrypt(key, encrypted) # => "secret message"
|
42
44
|
```
|
43
45
|
|
44
|
-
|
46
|
+
### Encrypting a message to a Bitcoin address
|
47
|
+
|
48
|
+
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:
|
45
49
|
|
46
50
|
```ruby
|
47
|
-
|
51
|
+
public_key_hex =
|
52
|
+
"04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb"\
|
53
|
+
"649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"
|
54
|
+
encrypted = ECIES::Crypt.new.encrypt(public_key_hex, 'you rock!')
|
48
55
|
```
|
49
56
|
|
50
|
-
|
57
|
+
To decrypt this message, Satoshi would follow these steps:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
private_key_hex = "<satoshi's private key>"
|
61
|
+
ECIES::Crypt.new.decrypt(private_key_hex, encrypted) # => "you rock!"
|
62
|
+
```
|
63
|
+
|
64
|
+
### Default parameters
|
65
|
+
|
66
|
+
By default, when constructing a new `ECIES::Crypt` object, it will use the following parameters for ECIES:
|
67
|
+
|
68
|
+
- KDF: ANSI-X9.63-KDF with SHA256
|
69
|
+
- MAC: HMAC-SHA-256-128
|
70
|
+
- Cipher: AES-256-CTR
|
71
|
+
- EC Group: secp256k1
|
72
|
+
|
73
|
+
These defaults work well for encrypting messages to bitcoin keys. This library also supports alternate algorithms as described in the below 'Compatibility' section. In order to utilize these other algorithms, initialize an `ECIES::Crypt` object with alternate parameters (see the `ECIES::Crypt.new` documentation for details). The `Crypt` object must be initialized with the same parameters when encrypting and decrypting messages.
|
51
74
|
|
52
75
|
## Compatibility
|
53
76
|
|
@@ -75,7 +98,7 @@ The sec1-v2 document allows for a many combinations of various algorithms for EC
|
|
75
98
|
- HMAC-SHA-256-128
|
76
99
|
- HMAC-SHA-256-256
|
77
100
|
- HMAC-SHA-384-192
|
78
|
-
- HMAC-SHA-384-384 (I believe sec1-v2 has a typo here, they state "HMAC-SHA-384-284". 284 bits would be 35.5 bytes, which is
|
101
|
+
- HMAC-SHA-384-384 (I believe sec1-v2 has a typo here, they state "HMAC-SHA-384-284". 284 bits would be 35.5 bytes, which is nonsensical)
|
79
102
|
- HMAC-SHA-512-256
|
80
103
|
- HMAC-SHA-512-512
|
81
104
|
- Not supported:
|
@@ -100,6 +123,14 @@ The sec1-v2 document allows for a many combinations of various algorithms for EC
|
|
100
123
|
|
101
124
|
Ruby 2.0 and above.
|
102
125
|
|
126
|
+
## Contributing
|
127
|
+
|
128
|
+
Bug reports and pull requests welcome! I happily accept any feedback that can improve this library's security.
|
129
|
+
|
130
|
+
## Disclaimer
|
131
|
+
|
132
|
+
While I have taken every effort to make this library as secure as possible, it is still an early version and has not yet been reviewed by a wide audience. Use at your own risk.
|
133
|
+
|
103
134
|
## Documentation
|
104
135
|
|
105
136
|
For complete documentation, see the [ECIES page on RubyDoc.info](http://rubydoc.info/gems/ecies).
|
data/ecies.gemspec
CHANGED
@@ -6,6 +6,11 @@ Gem::Specification.new do |s|
|
|
6
6
|
s.authors = ['Stephen McCarthy']
|
7
7
|
s.email = 'sjmccarthy@gmail.com'
|
8
8
|
s.summary = 'Elliptical Curve Integrated Encryption System (ECIES), as specified by SEC 1 - Ver. 2.0'
|
9
|
+
s.description = <<-DESCRIPTION
|
10
|
+
ECIES is a public-key encryption scheme based on ECC. It can be used to encrypt
|
11
|
+
messages to bitcoin addresses with keys published on the blockchain, and
|
12
|
+
subsequently to decrypt messages by the holders of the address's private key.
|
13
|
+
DESCRIPTION
|
9
14
|
s.homepage = 'https://github.com/jamoes/ecies'
|
10
15
|
s.license = 'MIT'
|
11
16
|
|
data/lib/ecies/crypt.rb
CHANGED
@@ -27,6 +27,9 @@ 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`.
|
30
33
|
# @param kdf_digest [String,OpenSSL::Digest,nil] The digest algorithm to
|
31
34
|
# use for KDF. If not specified, the `digest` argument will be used.
|
32
35
|
# @param mac_digest [String,OpenSSL::Digest,nil] The digest algorithm to
|
@@ -35,8 +38,9 @@ module ECIES
|
|
35
38
|
# info used for KDF, also known as SharedInfo1.
|
36
39
|
# @param mac_shared_info [String] Optional. A string containing the shared
|
37
40
|
# info used for MAC, also known as SharedInfo2.
|
38
|
-
def initialize(cipher: 'AES-256-CTR', digest: 'SHA256', mac_length: :half, kdf_digest: nil, mac_digest: nil, kdf_shared_info: '', mac_shared_info: '')
|
41
|
+
def initialize(cipher: 'AES-256-CTR', digest: 'SHA256', mac_length: :half, ec_group: 'secp256k1', kdf_digest: nil, mac_digest: nil, kdf_shared_info: '', mac_shared_info: '')
|
39
42
|
@cipher = OpenSSL::Cipher.new(cipher)
|
43
|
+
@ec_group = OpenSSL::PKey::EC::Group.new(ec_group)
|
40
44
|
@mac_digest = OpenSSL::Digest.new(mac_digest || digest)
|
41
45
|
@kdf_digest = OpenSSL::Digest.new(kdf_digest || digest)
|
42
46
|
@kdf_shared_info = kdf_shared_info
|
@@ -53,10 +57,17 @@ module ECIES
|
|
53
57
|
|
54
58
|
# Encrypts a message to a public key using ECIES.
|
55
59
|
#
|
56
|
-
#
|
60
|
+
# @param key [OpenSSL::EC:PKey,String] The public key. An OpenSSL::EC:PKey
|
61
|
+
# containing the public key, or a hex-encoded string representing the
|
62
|
+
# public key on this Crypt's `ec_group`.
|
57
63
|
# @param message [String] The plain-text message.
|
58
64
|
# @return [String] The octet string of the encrypted message.
|
59
65
|
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
|
60
71
|
key.public_key? or raise "Must have public key to encrypt"
|
61
72
|
@cipher.reset
|
62
73
|
|
@@ -83,9 +94,17 @@ module ECIES
|
|
83
94
|
# Decrypts a message with a private key using ECIES.
|
84
95
|
#
|
85
96
|
# @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`.
|
86
100
|
# @param encrypted_message [String] Octet string of the encrypted message.
|
87
101
|
# @return [String] The plain-text message.
|
88
102
|
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
|
89
108
|
key.private_key? or raise "Must have private key to decrypt"
|
90
109
|
@cipher.reset
|
91
110
|
|
data/lib/ecies/version.rb
CHANGED
data/spec/crypt_spec.rb
CHANGED
@@ -12,6 +12,35 @@ describe ECIES::Crypt do
|
|
12
12
|
expect(crypt.decrypt(key, encrypted)).to eq 'secret'
|
13
13
|
end
|
14
14
|
|
15
|
+
it 'Supports hex-encoded keys' do
|
16
|
+
key = OpenSSL::PKey::EC.new('secp256k1').generate_key
|
17
|
+
public_key_hex = key.public_key.to_bn.to_s(16)
|
18
|
+
private_key_hex = key.private_key.to_s(16)
|
19
|
+
|
20
|
+
crypt = ECIES::Crypt.new
|
21
|
+
|
22
|
+
encrypted = crypt.encrypt(public_key_hex, 'secret')
|
23
|
+
expect(crypt.decrypt(private_key_hex, encrypted)).to eq 'secret'
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'Supports other EC curves' do
|
27
|
+
key = OpenSSL::PKey::EC.new('secp224k1').generate_key
|
28
|
+
crypt = ECIES::Crypt.new(ec_group: key.group)
|
29
|
+
|
30
|
+
encrypted = crypt.encrypt(key, 'secret')
|
31
|
+
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
|
+
end
|
36
|
+
|
37
|
+
it 'Detects invalid hex-encoded points' do
|
38
|
+
key = OpenSSL::PKey::EC.new('secp224k1').generate_key
|
39
|
+
public_key_hex = key.public_key.to_bn.to_s(16)
|
40
|
+
|
41
|
+
expect{ ECIES::Crypt.new.encrypt(public_key_hex, 'secret') }.to raise_error(OpenSSL::PKey::EC::Point::Error)
|
42
|
+
end
|
43
|
+
|
15
44
|
it 'Encrypts to known values' do
|
16
45
|
OpenSSL::PKey::EC.class_eval do
|
17
46
|
# Overwrites `generate_key` for both the test code below, and the
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ecies
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen McCarthy
|
@@ -30,7 +30,7 @@ cert_chain:
|
|
30
30
|
kts216EGG4oP6dVuZmf2Ii2F4lQTBDdZM/cisW8jCkO7KeEzJAPhIw1JJwHltHya
|
31
31
|
0TpOI3t2Mz/FJ+rudtz9PJ/d8QvhrF7M7+qH4w==
|
32
32
|
-----END CERTIFICATE-----
|
33
|
-
date: 2018-04-
|
33
|
+
date: 2018-04-19 00:00:00.000000000 Z
|
34
34
|
dependencies:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: bundler
|
@@ -130,7 +130,10 @@ dependencies:
|
|
130
130
|
- - "~>"
|
131
131
|
- !ruby/object:Gem::Version
|
132
132
|
version: '3'
|
133
|
-
description:
|
133
|
+
description: |2
|
134
|
+
ECIES is a public-key encryption scheme based on ECC. It can be used to encrypt
|
135
|
+
messages to bitcoin addresses with keys published on the blockchain, and
|
136
|
+
subsequently to decrypt messages by the holders of the address's private key.
|
134
137
|
email: sjmccarthy@gmail.com
|
135
138
|
executables: []
|
136
139
|
extensions: []
|
metadata.gz.sig
CHANGED
Binary file
|