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 +5 -5
- data/.ruby-version +1 -1
- data/.travis.yml +21 -0
- data/CHANGELOG.md +21 -0
- data/README.md +8 -5
- data/aes_key_wrap.gemspec +6 -2
- data/lib/aes_key_wrap.rb +35 -6
- data/lib/aes_key_wrap/version.rb +1 -1
- metadata +26 -15
- data/.rspec +0 -2
- data/Rakefile +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 975893714de4407b4e7810177589efcc6602e32a3586b94b525ba6efc5d61c8e
|
4
|
+
data.tar.gz: 8f10761ae857d59739e0b88c875348374018ec9537da21be113dea8eab97a97f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eac3ed6586dd4aff0b76bab567359969809c6e326aa68210c058f5509d94cecb7c7d35f059f8c8932524dd302e29a2221f0943a1a445111875becf0af2c8c394
|
7
|
+
data.tar.gz: db11cf15a329f48fe0ba8d451c98a63c8bc47bf1dcbd3dd0f4de7227e039a4f4b1c673b8060a945de2d5a3b642dfa19032aa7b9fa3ca5786d83005a55d76abd8
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.7
|
data/.travis.yml
CHANGED
@@ -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
|
data/CHANGELOG.md
ADDED
@@ -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
|
[](https://travis-ci.org/tomdalling/aes_key_wrap)
|
2
|
+
[](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 =
|
20
|
-
|
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
|
-
|
32
|
+
There also `unwrap!`, which throws an exception if unwrapping fails, instead of
|
33
|
+
returning nil.
|
31
34
|
|
32
35
|
## Contributing
|
33
36
|
|
data/aes_key_wrap.gemspec
CHANGED
@@ -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 '
|
20
|
-
spec.add_development_dependency '
|
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
|
|
data/lib/aes_key_wrap.rb
CHANGED
@@ -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
|
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
|
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
|
-
#
|
67
|
-
#
|
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
|
|
data/lib/aes_key_wrap/version.rb
CHANGED
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
|
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:
|
11
|
+
date: 2020-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: test_bench
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
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: '
|
26
|
+
version: '1.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: gem-release
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
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:
|
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
|
-
|
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