aes_key_wrap 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![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 =
|
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