aes_key_wrap 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 259a4c54a9c1e9d7c04b0c5af1853702ab9762a0
4
+ data.tar.gz: c576c30659e2f1ade052b41e988ab9045fd99afd
5
+ SHA512:
6
+ metadata.gz: 491f321a2568db3fdc4e605c19eb1226163dd3f321598eb0973b295c2fa4ce5b674a7eb4f484a87eac197d425ce7a36164b3ddbcb6b46f3d4c7336b1442cba3d
7
+ data.tar.gz: 04be2bf30c6aee910095d4438a1f60be36f6f72abe1dfd4ce2788df06268dc72cc7a9ad56f50aacc2cdf59ff084392209805da82731e31009e514dcc6b5e749d
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in aes_key_wrap.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Tom Dalling
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # AESKeyWrap
2
+
3
+ A Ruby implementation of AES Key Wrap, a.k.a RFC 3394, a.k.a NIST Key Wrap.
4
+
5
+ ## Usage
6
+
7
+ To wrap a key, call `AESKeyWrap.wrap` with:
8
+
9
+ - The plain text key
10
+ - A key-encrypting key (KEK)
11
+ - An "initial value" (optional)
12
+
13
+ ```ruby
14
+ require 'aes_key_wrap'
15
+ plaintext_key = ['00112233445566778899AABBCCDDEEFF'].pack('H*') #binary string
16
+ kek = ['000102030405060708090A0B0C0D0E0F'].pack('H*') # binary string
17
+ iv = 0xDEADBEEFC0FFEEEE
18
+ wrapped_key = AESKeyWrap.wrap(plaintext_key, kek, iv)
19
+ ```
20
+
21
+ To unwrap a key, call `AESKeyWrap.unwrap`:
22
+
23
+ ```ruby
24
+ unwrapped = AESKeyWrap.unwrap(wrapped_key, kek, iv)
25
+ ```
26
+
27
+ There also `unwrap!`, which throws an exception if unwrapping
28
+ fails, instead of returning nil:
29
+
30
+ ## Contributing
31
+
32
+ Make sure it's got tests, then do the usual fork and pull request hooha.
33
+
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'aes_key_wrap/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'aes_key_wrap'
8
+ spec.version = AESKeyWrap::VERSION
9
+ spec.authors = ['Tom Dalling']
10
+ spec.email = ['tom' + '@tom' + 'dalling.com']
11
+
12
+ spec.summary = %q{A Ruby implementation of AES Key Wrap, a.k.a RFC 3394, a.k.a NIST Key Wrap.}
13
+ spec.homepage = 'https://github.com/tomdalling/aes_key_wrap'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.require_paths = ['lib']
18
+
19
+ spec.add_development_dependency 'bundler', '~> 1.8'
20
+ spec.add_development_dependency 'rake', '~> 10.0'
21
+ spec.add_development_dependency 'rspec', '~> 3.2.0'
22
+ end
23
+
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "aes_key_wrap"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,124 @@
1
+ ##
2
+ # A Ruby implementation of AES Key Wrap, a.k.a RFC 3394, a.k.a NIST Key Wrapping
3
+ #
4
+ module AESKeyWrap
5
+ DEFAULT_IV = 0xA6A6A6A6A6A6A6A6
6
+ UnwrapFailedError = Class.new(StandardError)
7
+
8
+ class << self
9
+
10
+ ##
11
+ # Wraps a key using a key-encrypting key (KEK)
12
+ #
13
+ # This is an implementation of the "index based" algorithm
14
+ # specified in section 2.2.1 of RFC 3394:
15
+ # http://www.ietf.org/rfc/rfc3394.txt
16
+ #
17
+ # @param unwrapped_key [String] The plaintext key to be wrapped, as a binary string
18
+ # @param kek [String] The key-encrypting key, as a binary_string
19
+ # @param iv [Integer] The "initial value", as unsigned 64bit integer
20
+ # @return [String] The wrapped key, as a binary string
21
+ #
22
+ def wrap(unwrapped_key, kek, iv=DEFAULT_IV)
23
+ # 1) Initialize variables.
24
+ #
25
+ # P: buffer (from unwrapped_key)
26
+ # A: buffer[0]
27
+ # R: buffer
28
+ # K: kek
29
+ # n: block_count
30
+ # AES: aes(:encrypt, _, _)
31
+ # IV: iv
32
+ buffer = [iv] + unwrapped_key.unpack('Q>*')
33
+ block_count = buffer.size - 1
34
+
35
+ # 2) Calculate intermediate values.
36
+ # t: round
37
+ 0.upto(5) do |j|
38
+ 1.upto(block_count) do |i|
39
+ round = block_count*j + i
40
+ # In
41
+ data = [buffer[0], buffer[i]].pack('Q>2')
42
+ buffer[0], buffer[i] = aes(:encrypt, kek, data).unpack('Q>2')
43
+ # Enc
44
+ buffer[0] = buffer[0] ^ round
45
+ # XorT
46
+ end
47
+ end
48
+
49
+ # 3) Output the results.
50
+ buffer.pack('Q>*')
51
+ end
52
+
53
+ ##
54
+ # Unwraps an encrypted key using a key-encrypting key (KEK)
55
+ #
56
+ # This is an implementation of the "index based" algorithm
57
+ # specified in section 2.2.2 of RFC 3394:
58
+ # http://www.ietf.org/rfc/rfc3394.txt
59
+ #
60
+ # @param wrapped_key [String] The wrapped key (cyphertext), as a binary string
61
+ # @param kek [String] The key-encrypting key, as a binary string
62
+ # @param expected_iv [Integer] The IV used to wrap the key, as an unsigned 64bit integer
63
+ # @return [String] The unwrapped (plaintext) key as a binary string, or
64
+ # `nil` if unwrapping failed due to `expected_iv` not matching the
65
+ # decrypted IV
66
+ #
67
+ # @see #unwrap!
68
+ #
69
+ def unwrap(wrapped_key, kek, expected_iv=DEFAULT_IV)
70
+ # 1) Initialize variables.
71
+ #
72
+ # C: buffer (from wrapped_key)
73
+ # A: buffer[0]
74
+ # R: buffer
75
+ # n: block_count
76
+ # K: kek
77
+ # AES-1: aes(:decrypt, _, _)
78
+ buffer = wrapped_key.unpack('Q>*')
79
+ block_count = buffer.size - 1
80
+
81
+ # 2) Calculate intermediate values.
82
+ # t: round
83
+ 5.downto(0) do |j|
84
+ block_count.downto(1) do |i|
85
+ round = block_count*j + i
86
+ # In
87
+ buffer[0] = buffer[0] ^ round
88
+ # XorT
89
+ data = [buffer[0], buffer[i]].pack('Q>2')
90
+ buffer[0], buffer[i] = aes(:decrypt, kek, data).unpack('Q>2')
91
+ # Dec
92
+ end
93
+ end
94
+
95
+ # 3) Output the results.
96
+ if buffer[0] == expected_iv
97
+ buffer.drop(1).pack('Q>*')
98
+ else
99
+ nil
100
+ end
101
+ end
102
+
103
+ ##
104
+ # Exception-throwing version of #unwrap
105
+ #
106
+ # @see #unwrap
107
+ #
108
+ def unwrap!(*args)
109
+ unwrap(*args) || raise(UnwrapFailedError, 'Unwrapped IV does not match')
110
+ end
111
+
112
+ private
113
+
114
+ def aes(encrypt_or_decrypt, key, data)
115
+ decipher = OpenSSL::Cipher::AES.new(key.bytesize * 8, :ECB)
116
+ decipher.send(encrypt_or_decrypt)
117
+ decipher.key = key
118
+ decipher.padding = 0
119
+
120
+ decipher.update(data) + decipher.final
121
+ end
122
+ end
123
+ end
124
+
@@ -0,0 +1,3 @@
1
+ module AESKeyWrap
2
+ VERSION = '1.0.0'
3
+ end
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aes_key_wrap
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Tom Dalling
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.8'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.2.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.2.0
55
+ description:
56
+ email:
57
+ - tom@tomdalling.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".rspec"
64
+ - ".travis.yml"
65
+ - Gemfile
66
+ - LICENSE.txt
67
+ - README.md
68
+ - Rakefile
69
+ - aes_key_wrap.gemspec
70
+ - bin/console
71
+ - bin/setup
72
+ - lib/aes_key_wrap.rb
73
+ - lib/aes_key_wrap/version.rb
74
+ homepage: https://github.com/tomdalling/aes_key_wrap
75
+ licenses:
76
+ - MIT
77
+ metadata: {}
78
+ post_install_message:
79
+ rdoc_options: []
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ requirements: []
93
+ rubyforge_project:
94
+ rubygems_version: 2.4.5
95
+ signing_key:
96
+ specification_version: 4
97
+ summary: A Ruby implementation of AES Key Wrap, a.k.a RFC 3394, a.k.a NIST Key Wrap.
98
+ test_files: []