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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 33b1046a11dbb7f36abc039da9e124a16f3db9751cfedbc869bde97b01b08091
4
- data.tar.gz: 2138b78219252211b76b8f63db73489c94ec7be3cef8c922c689d1cb5ca29a94
3
+ metadata.gz: b9b17b5e59affac68ce47a7afe053747c90c287201202fffe9a97550644d6c5c
4
+ data.tar.gz: 161fb791e8f8e67252ce565fa06fd1196228629e45b3ccbc07384b5b9f207a4a
5
5
  SHA512:
6
- metadata.gz: 233a031a01b0a1db77727ce486b9a419361b69b0a894c2e333c4769772abfc4850d2715db01bccffd8c714b5ae99266e45c9af880313d66c4eabeb24cc1aae99
7
- data.tar.gz: 644a95d9c983e7c2b3711f0f89369867cacbd3aa4674237864c35bf312e37e98d58680854d73e118fbb72e21d9cbb1f8e4da60cb5bc5f7ea5b51959604f0e757
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) # => 'secret message'
43
+ crypt.decrypt(key, encrypted) # => "secret message"
42
44
  ```
43
45
 
44
- When constructing a `Crypt` object, the default hash digest function is 'SHA256', and the default cipher algorithm is 'AES-256-CTR'. You can also specify alternative cipher or digest algorithms. For example:
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
- crypt = ECIES::Crypt.new(cipher: 'AES-256-CBC', digest: 'SHA512')
51
+ public_key_hex =
52
+ "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb"\
53
+ "649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"
54
+ encrypted = ECIES::Crypt.new.encrypt(public_key_hex, 'you rock!')
48
55
  ```
49
56
 
50
- The `Crypt` object must be initialized with the same parameters when encrypting and decrypting messages.
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 non-sensical)
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
- # # @param key [OpenSSL::EC:PKey] The public key.
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
@@ -1,4 +1,4 @@
1
1
  module ECIES
2
2
  # This gem's version.
3
- VERSION = '0.1.0'
3
+ VERSION = '0.2.0'
4
4
  end
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.1.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-18 00:00:00.000000000 Z
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