aes_key_wrap 1.0.1 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 9c0f645c56b2c0ae94cabd1077535d2a46674367
4
- data.tar.gz: f9db99d515349bd73276c3dab991965df415ea4d
2
+ SHA256:
3
+ metadata.gz: 975893714de4407b4e7810177589efcc6602e32a3586b94b525ba6efc5d61c8e
4
+ data.tar.gz: 8f10761ae857d59739e0b88c875348374018ec9537da21be113dea8eab97a97f
5
5
  SHA512:
6
- metadata.gz: e1bc33d21b3971adca4cfe8ebb810ff278e810507dd22462df83a99cd614a95b8bac81ee6bfbe86cb5be386aa97404e8d04ca8f735431091a228fa88ec75159a
7
- data.tar.gz: d26e72d021f09467fc09c8cd31bd068fb41001ae0d5619e91d6944746c9adff0f35bd78384bab260148f03b3b4e76d843a24d007c7b753aacc72a2c35bc23665
6
+ metadata.gz: eac3ed6586dd4aff0b76bab567359969809c6e326aa68210c058f5509d94cecb7c7d35f059f8c8932524dd302e29a2221f0943a1a445111875becf0af2c8c394
7
+ data.tar.gz: db11cf15a329f48fe0ba8d451c98a63c8bc47bf1dcbd3dd0f4de7227e039a4f4b1c673b8060a945de2d5a3b642dfa19032aa7b9fa3ca5786d83005a55d76abd8
@@ -1 +1 @@
1
- 2.2.0
1
+ 2.7
@@ -1 +1,22 @@
1
+ script: bundle exec ruby test/aes_key_wrap.rb
1
2
  language: ruby
3
+
4
+ # test on old rubies
5
+ rvm:
6
+ - 2.3.8
7
+ - 2.4.10
8
+ - 2.5.8
9
+ - 2.6.6
10
+
11
+ # run latest ruby differently (run codeclimate)
12
+ matrix:
13
+ include:
14
+ - rvm: 2.7.1
15
+ # code climate config
16
+ env: CC_TEST_REPORTER_ID=112d90dacd3bbf36bbf39282309a52581175ae544be2cf8ef3b8c0c0221515f5
17
+ before_script:
18
+ - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
19
+ - chmod +x ./cc-test-reporter
20
+ - ./cc-test-reporter before-build
21
+ after_script:
22
+ - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
@@ -0,0 +1,21 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [1.1.0] - 2020-07-12
8
+ ### Added
9
+ - IV arguments can be either `String`s or `Integer`s. Previously, they could
10
+ only be `Integer`s. This is a backwards-compatible addition as long as you
11
+ aren't doing something freaky with IVs, like using negative numbers (they are
12
+ supposed to be unsigned).
13
+
14
+ ## [1.0.1] - 2015-04-24
15
+ ### Fixed
16
+ - Didn't work unless you had `require 'openssl'` somewhere first. The gem now
17
+ `require`s its own dependencies, surprising no one.
18
+
19
+ ## [1.0.0] - 2015-04-24
20
+ ### Added
21
+ - Everything (Initial release)
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  [![Build Status](https://travis-ci.org/tomdalling/aes_key_wrap.svg?branch=master)](https://travis-ci.org/tomdalling/aes_key_wrap)
2
+ [![Test Coverage](https://codeclimate.com/github/tomdalling/aes_key_wrap/badges/coverage.svg)](https://codeclimate.com/github/tomdalling/aes_key_wrap)
2
3
 
3
4
  # AESKeyWrap
4
5
 
@@ -14,20 +15,22 @@ To wrap a key, call `AESKeyWrap.wrap` with:
14
15
 
15
16
  ```ruby
16
17
  require 'aes_key_wrap'
18
+
17
19
  plaintext_key = ['00112233445566778899AABBCCDDEEFF'].pack('H*') #binary string
18
20
  kek = ['000102030405060708090A0B0C0D0E0F'].pack('H*') # binary string
19
- iv = 0xDEADBEEFC0FFEEEE
20
- wrapped_key = AESKeyWrap.wrap(plaintext_key, kek, iv)
21
+ iv = ['DEADBEEFC0FFEEEE'].pack("H*") # binary string (always 8 bytes)
22
+
23
+ wrapped_key = AESKeyWrap.wrap(plaintext_key, kek, iv) # iv is optional
21
24
  ```
22
25
 
23
26
  To unwrap a key, call `AESKeyWrap.unwrap`:
24
27
 
25
28
  ```ruby
26
- unwrapped = AESKeyWrap.unwrap(wrapped_key, kek, iv)
29
+ unwrapped = AESKeyWrap.unwrap(wrapped_key, kek, iv) # iv is optional
27
30
  ```
28
31
 
29
- There also `unwrap!`, which throws an exception if unwrapping
30
- fails, instead of returning nil.
32
+ There also `unwrap!`, which throws an exception if unwrapping fails, instead of
33
+ returning nil.
31
34
 
32
35
  ## Contributing
33
36
 
@@ -16,7 +16,11 @@ Gem::Specification.new do |spec|
16
16
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
17
  spec.require_paths = ['lib']
18
18
 
19
- spec.add_development_dependency 'rake', '~> 10.0'
20
- spec.add_development_dependency 'rspec', '~> 3.2.0'
19
+ spec.add_development_dependency 'test_bench', '~> 1.0'
20
+ spec.add_development_dependency 'gem-release'
21
+
22
+ # code climate doesn't support v0.18+
23
+ # see: https://github.com/codeclimate/test-reporter/issues/413
24
+ spec.add_development_dependency 'simplecov', '< 0.18'
21
25
  end
22
26
 
@@ -5,6 +5,8 @@ require 'openssl'
5
5
  #
6
6
  module AESKeyWrap
7
7
  DEFAULT_IV = 0xA6A6A6A6A6A6A6A6
8
+ IV_SIZE = 8 # bytes
9
+
8
10
  UnwrapFailedError = Class.new(StandardError)
9
11
 
10
12
  class << self
@@ -18,7 +20,9 @@ module AESKeyWrap
18
20
  #
19
21
  # @param unwrapped_key [String] The plaintext key to be wrapped, as a binary string
20
22
  # @param kek [String] The key-encrypting key, as a binary_string
21
- # @param iv [Integer] The "initial value", as unsigned 64bit integer
23
+ # @param iv [Integer, String] The "initial value", as either an unsigned
24
+ # 64-bit integer (e.g. `0xDEADBEEFC0FFEEEE`) or an 8-byte string (e.g.
25
+ # `"\xDE\xAD\xBE\xEF\xC0\xFF\xEE\xEE"`).
22
26
  # @return [String] The wrapped key, as a binary string
23
27
  #
24
28
  def wrap(unwrapped_key, kek, iv=DEFAULT_IV)
@@ -31,7 +35,7 @@ module AESKeyWrap
31
35
  # n: block_count
32
36
  # AES: aes(:encrypt, _, _)
33
37
  # IV: iv
34
- buffer = [iv] + unwrapped_key.unpack('Q>*')
38
+ buffer = [coerce_uint64(iv)] + unwrapped_key.unpack('Q>*')
35
39
  block_count = buffer.size - 1
36
40
 
37
41
  # 2) Calculate intermediate values.
@@ -61,10 +65,12 @@ module AESKeyWrap
61
65
  #
62
66
  # @param wrapped_key [String] The wrapped key (cyphertext), as a binary string
63
67
  # @param kek [String] The key-encrypting key, as a binary string
64
- # @param expected_iv [Integer] The IV used to wrap the key, as an unsigned 64bit integer
68
+ # @param expected_iv [Integer, String] The IV used to wrap the key, as either
69
+ # an unsigned 64-bit integer (e.g. `0xDEADBEEFC0FFEEEE`) or an 8-byte
70
+ # string (e.g. `"\xDE\xAD\xBE\xEF\xC0\xFF\xEE\xEE"`).
65
71
  # @return [String] The unwrapped (plaintext) key as a binary string, or
66
- # `nil` if unwrapping failed due to `expected_iv` not matching the
67
- # decrypted IV
72
+ # `nil` if unwrapping failed due to `expected_iv` not matching the
73
+ # decrypted IV
68
74
  #
69
75
  # @see #unwrap!
70
76
  #
@@ -95,7 +101,7 @@ module AESKeyWrap
95
101
  end
96
102
 
97
103
  # 3) Output the results.
98
- if buffer[0] == expected_iv
104
+ if buffer[0] == coerce_uint64(expected_iv)
99
105
  buffer.drop(1).pack('Q>*')
100
106
  else
101
107
  nil
@@ -113,6 +119,8 @@ module AESKeyWrap
113
119
 
114
120
  private
115
121
 
122
+ MAX_UINT64 = 0xFFFFFFFFFFFFFFFF
123
+
116
124
  def aes(encrypt_or_decrypt, key, data)
117
125
  decipher = OpenSSL::Cipher::AES.new(key.bytesize * 8, :ECB)
118
126
  decipher.send(encrypt_or_decrypt)
@@ -121,6 +129,27 @@ module AESKeyWrap
121
129
 
122
130
  decipher.update(data) + decipher.final
123
131
  end
132
+
133
+ def coerce_uint64(value)
134
+ case value
135
+ when Integer
136
+ if value > MAX_UINT64
137
+ raise ArgumentError, "IV is too large to fit in a 64-bit unsigned integer"
138
+ elsif value < 0
139
+ raise ArgumentError, "IV is not an unsigned integer (it's negative)"
140
+ else
141
+ value
142
+ end
143
+ when String
144
+ if value.bytesize == IV_SIZE
145
+ value.unpack("Q>").first
146
+ else
147
+ raise ArgumentError, "IV is not #{IV_SIZE} bytes long"
148
+ end
149
+ else
150
+ raise ArgumentError, "IV is not valid: #{value.inspect}"
151
+ end
152
+ end
124
153
  end
125
154
  end
126
155
 
@@ -1,3 +1,3 @@
1
1
  module AESKeyWrap
2
- VERSION = '1.0.1'
2
+ VERSION = '1.1.0'
3
3
  end
metadata CHANGED
@@ -1,43 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aes_key_wrap
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Dalling
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-24 00:00:00.000000000 Z
11
+ date: 2020-07-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rake
14
+ name: test_bench
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '10.0'
19
+ version: '1.0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '10.0'
26
+ version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rspec
28
+ name: gem-release
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 3.2.0
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: simplecov
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "<"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.18'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "<"
39
53
  - !ruby/object:Gem::Version
40
- version: 3.2.0
54
+ version: '0.18'
41
55
  description:
42
56
  email:
43
57
  - tom@tomdalling.com
@@ -46,13 +60,12 @@ extensions: []
46
60
  extra_rdoc_files: []
47
61
  files:
48
62
  - ".gitignore"
49
- - ".rspec"
50
63
  - ".ruby-version"
51
64
  - ".travis.yml"
65
+ - CHANGELOG.md
52
66
  - Gemfile
53
67
  - LICENSE.txt
54
68
  - README.md
55
- - Rakefile
56
69
  - aes_key_wrap.gemspec
57
70
  - bin/console
58
71
  - bin/setup
@@ -77,10 +90,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
77
90
  - !ruby/object:Gem::Version
78
91
  version: '0'
79
92
  requirements: []
80
- rubyforge_project:
81
- rubygems_version: 2.4.5
93
+ rubygems_version: 3.1.2
82
94
  signing_key:
83
95
  specification_version: 4
84
96
  summary: A Ruby implementation of AES Key Wrap, a.k.a RFC 3394, a.k.a NIST Key Wrap.
85
97
  test_files: []
86
- has_rdoc:
data/.rspec DELETED
@@ -1,2 +0,0 @@
1
- --format documentation
2
- --color
data/Rakefile DELETED
@@ -1,9 +0,0 @@
1
- require "bundler/gem_tasks"
2
-
3
- begin
4
- require 'rspec/core/rake_task'
5
- RSpec::Core::RakeTask.new(:spec)
6
- rescue LoadError
7
- end
8
-
9
- task :default => :spec