miscreant 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c3b2740135b6e13589326c9b8f2c926edff86516
4
+ data.tar.gz: b4327cc7c72ce38aaec0208f967c67fdceb2508f
5
+ SHA512:
6
+ metadata.gz: b24730c57fd7ef67a4e7699a63c05454875ffec00366212a31445111525b7fbd953d122f8ff88e1871e0f7caee792780394382b7b9021fb9a83772fbf8d2ad6f
7
+ data.tar.gz: ceafedfa57c9b6d6ca7a72d8d50e31041af4d9c5113ea7e2d6482ef49a456914411138d6a75f43f5f67340f8aed5fe71bac0a5bbe7581734c2379681e3e1cf15
@@ -0,0 +1,13 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /.rakeTasks
4
+ /Gemfile.lock
5
+ /_yardoc/
6
+ /coverage/
7
+ /doc/
8
+ /pkg/
9
+ /spec/reports/
10
+ /tmp/
11
+
12
+ # rspec failure tracking
13
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --color
2
+ --format=documentation
3
+ --order random
4
+ --require spec_helper
@@ -0,0 +1,34 @@
1
+ AllCops:
2
+ DisplayCopNames: true
3
+
4
+ #
5
+ # Metrics
6
+ #
7
+
8
+ Metrics/AbcSize:
9
+ Enabled: false
10
+
11
+ Metrics/BlockLength:
12
+ Max: 50
13
+
14
+ Metrics/CyclomaticComplexity:
15
+ Enabled: false
16
+
17
+ Metrics/PerceivedComplexity:
18
+ Enabled: false
19
+
20
+ Metrics/ClassLength:
21
+ Max: 100
22
+
23
+ Metrics/LineLength:
24
+ Max: 128
25
+
26
+ Metrics/MethodLength:
27
+ Max: 25
28
+
29
+ #
30
+ # Style
31
+ #
32
+
33
+ Style/StringLiterals:
34
+ EnforcedStyle: double_quotes
@@ -0,0 +1 @@
1
+ 2.4.1
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gemspec
6
+
7
+ group :development, :test do
8
+ gem "benchmark-ips"
9
+ gem "guard-rspec"
10
+ gem "rake"
11
+ gem "rspec", "~> 3.5"
12
+ gem "rubocop", "0.49.1"
13
+ gem "tjson", "~> 0.5"
14
+ end
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2013-2017 John Downey, The Miscreant Developers
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,142 @@
1
+ # miscreant.rb [![Latest Version][gem-shield]][gem-link] [![Build Status][build-image]][build-link] [![Code Climate][codeclimate-image]][codeclimate-link] [![MIT licensed][license-image]][license-link]
2
+
3
+ [gem-shield]: https://badge.fury.io/rb/miscreant.svg
4
+ [gem-link]: https://rubygems.org/gems/miscreant
5
+ [build-image]: https://secure.travis-ci.org/miscreant/miscreant.svg?branch=master
6
+ [build-link]: http://travis-ci.org/miscreant/miscreant
7
+ [codeclimate-image]: https://codeclimate.com/github/miscreant/miscreant/badges/gpa.svg
8
+ [codeclimate-link]: https://codeclimate.com/github/miscreant/miscreant
9
+ [license-image]: https://img.shields.io/badge/license-MIT-blue.svg
10
+ [license-link]: https://github.com/miscreant/miscreant/blob/master/LICENSE.txt
11
+
12
+ > The best crypto you've never heard of, brought to you by [Phil Rogaway]
13
+
14
+ Ruby implementation of **Miscreant**: Advanced symmetric encryption using the
15
+ AES-SIV ([RFC 5297]) and [CHAIN] constructions, providing easy-to-use (or
16
+ rather, hard-to-misuse) encryption of individual messages or message streams.
17
+
18
+ **AES-SIV** provides [nonce-reuse misuse-resistance] (NRMR): accidentally
19
+ reusing a nonce with this construction is not a security catastrophe,
20
+ unlike it is with more popular AES encryption modes like [AES-GCM].
21
+ With **AES-SIV**, the worst outcome of reusing a nonce is an attacker
22
+ can see you've sent the same plaintext twice, as opposed to almost all other
23
+ AES modes where it can facilitate [chosen ciphertext attacks] and/or
24
+ full plaintext recovery.
25
+
26
+ For more information, see the [toplevel README.md].
27
+
28
+ [Phil Rogaway]: https://en.wikipedia.org/wiki/Phillip_Rogaway
29
+ [AES-SIV]: https://www.iacr.org/archive/eurocrypt2006/40040377/40040377.pdf
30
+ [RFC 5297]: https://tools.ietf.org/html/rfc5297
31
+ [CHAIN]: http://web.cs.ucdavis.edu/~rogaway/papers/oae.pdf
32
+ [nonce-reuse misuse-resistance]: https://www.lvh.io/posts/nonce-misuse-resistance-101.html
33
+ [AES-GCM]: https://en.wikipedia.org/wiki/Galois/Counter_Mode
34
+ [chosen ciphertext attacks]: https://en.wikipedia.org/wiki/Chosen-ciphertext_attack
35
+ [toplevel README.md]: https://github.com/miscreant/miscreant/blob/master/README.md
36
+
37
+ ## Help and Discussion
38
+
39
+ Have questions? Want to suggest a feature or change?
40
+
41
+ * [Gitter]: web-based chat about miscreant projects including **miscreant.rb**
42
+ * [Google Group]: join via web or email ([miscreant+subscribe@googlegroups.com])
43
+
44
+ [Gitter]: https://gitter.im/miscreant/Lobby
45
+ [Google Group]: https://groups.google.com/forum/#!forum/miscreant
46
+ [miscreant+subscribe@googlegroups.com]: mailto:miscreant+subscribe@googlegroups.com
47
+
48
+ ## Security Notice
49
+
50
+ Though this library is written by cryptographic professionals, it has not
51
+ undergone a thorough security audit, and cryptographic professionals are still
52
+ humans that make mistakes. Use this library at your own risk.
53
+
54
+ ## Requirements
55
+
56
+ This library is tested against the following MRI versions:
57
+
58
+ - 2.2
59
+ - 2.3
60
+ - 2.4
61
+
62
+ Other Ruby versions may work, but are not officially supported.
63
+
64
+ ## Installation
65
+
66
+ Add this line to your application's Gemfile:
67
+
68
+ ```ruby
69
+ gem "miscreant"
70
+ ```
71
+
72
+ And then execute:
73
+
74
+ $ bundle
75
+
76
+ Or install it yourself as:
77
+
78
+ $ gem install miscreant
79
+
80
+ ## API
81
+
82
+ ### Miscreant::AES::SIV
83
+
84
+ The `Miscreant::AES::SIV` class provides the main interface to the **AES-SIV**
85
+ misuse resistant authenticated encryption function.
86
+
87
+ To make a new instance, pass in a 32-byte or 64-byte key. Note that these
88
+ options are twice the size of what you might be expecting (AES-SIV uses two
89
+ AES keys).
90
+
91
+ You can generate a random key using the `generate_key` method (default 32 bytes):
92
+
93
+ ```ruby
94
+ key_bytes = Miscreant::AES::SIV.generate_key
95
+ key = Miscreant::AES::SIV.new(key_bytes)
96
+ # => #<Miscreant::AES::SIV:0x007fe0109e85e8>
97
+ ```
98
+
99
+ #### Encryption (#seal)
100
+
101
+ The `Miscreant::AES::SIV#seal` method encrypts a message along with a set of
102
+ *associated data* message headers.
103
+
104
+ It's recommended to include a unique "nonce" value with each message. This
105
+ prevents those who may be observing your ciphertexts from being able to tell
106
+ if you encrypted the same message twice. However, unlike other cryptographic
107
+ algorithms where using a nonce has catastrophic security implications such as
108
+ key recovery, reusing a nonce with AES-SIV only leaks repeated ciphertexts to
109
+ attackers.
110
+
111
+ Example:
112
+
113
+ ```ruby
114
+ message = "Hello, world!"
115
+ nonce = SecureRandom.random_bytes(16)
116
+ ciphertext = key.seal(message, nonce)
117
+ ```
118
+
119
+ #### Decryption (#open)
120
+
121
+ The `Miscreant::AES::SIV#open` method decrypts a ciphertext with the given key.
122
+
123
+ Example:
124
+
125
+ ```ruby
126
+ message = "Hello, world!"
127
+ nonce = SecureRandom.random_bytes(16)
128
+ ciphertext = key.seal(message, nonce)
129
+ plaintext = key.open(ciphertext, nonce)
130
+ ```
131
+
132
+ ## Contributing
133
+
134
+ Bug reports and pull requests are welcome on GitHub at https://github.com/miscreant/miscreant
135
+
136
+ ## Copyright
137
+
138
+ Copyright (c) 2013-2017 John Downey, [The Miscreant Developers][AUTHORS].
139
+ See [LICENSE.txt] for further details.
140
+
141
+ [AUTHORS]: https://github.com/miscreant/miscreant/blob/master/AUTHORS.md
142
+ [LICENSE.txt]: https://github.com/miscreant/miscreant/blob/master/ruby/LICENSE.txt
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+
5
+ require "rspec/core/rake_task"
6
+ RSpec::Core::RakeTask.new
7
+
8
+ require "rubocop/rake_task"
9
+ RuboCop::RakeTask.new
10
+
11
+ task default: %w[spec rubocop]
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "openssl"
4
+ require "securerandom"
5
+
6
+ require "miscreant/version"
7
+
8
+ require "miscreant/aes"
9
+ require "miscreant/aes/siv"
10
+ require "miscreant/aes/cmac"
11
+ require "miscreant/util"
12
+
13
+ # Misuse-resistant symmetric encryption using the AES-SIV (RFC 5297) and CHAIN constructions
14
+ module Miscreant
15
+ # Parent of all cryptography-related errors
16
+ CryptoError = Class.new(StandardError)
17
+
18
+ # Ciphertext failed to verify as authentic
19
+ IntegrityError = Class.new(CryptoError)
20
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: binary
2
+ # frozen_string_literal: true
3
+
4
+ module Miscreant
5
+ # The Advanced Encryption Standard Block Cipher
6
+ module AES
7
+ # Size of an AES block (i.e. input/output from the AES function)
8
+ BLOCK_SIZE = 16
9
+
10
+ # A bytestring of all zeroes, the same length as an AES block
11
+ ZERO_BLOCK = ("\0" * BLOCK_SIZE).freeze
12
+ end
13
+ end
@@ -0,0 +1,77 @@
1
+ # encoding: binary
2
+ # frozen_string_literal: true
3
+
4
+ module Miscreant
5
+ module AES
6
+ # The AES-CMAC message authentication code
7
+ class CMAC
8
+ # Create a new AES-CMAC instance
9
+ #
10
+ # @param key [String] 16-byte or 32-byte Encoding::BINARY cryptographic key
11
+ #
12
+ # @return [Miscreant::AES::CMAC] new AES-CMAC instance
13
+ def initialize(key)
14
+ raise TypeError, "expected String, got #{key.class}" unless key.is_a?(String)
15
+ raise ArgumentError, "key must be Encoding::BINARY" unless key.encoding == Encoding::BINARY
16
+ raise ArgumentError, "key must be 32 or 64 bytes" unless [16, 32].include?(key.length)
17
+
18
+ # The only valid use of ECB mode: constructing higher-level cryptographic primitives
19
+ @cipher = OpenSSL::Cipher.new("AES-#{key.length * 8}-ECB")
20
+ @cipher.encrypt
21
+ @cipher.padding = 0
22
+ @cipher.key = key
23
+ @key1, @key2 = _generate_subkeys
24
+ end
25
+
26
+ # Inspect this AES-CMAC instance
27
+ #
28
+ # @return [String] description of this instance
29
+ def inspect
30
+ to_s
31
+ end
32
+
33
+ # Compute the AES-CMAC of the given input message in a single shot,
34
+ # outputting the MAC tag.
35
+ #
36
+ # Unlike other AES-CMAC implementations, this one does not support
37
+ # incremental processing/IUF operation. (Though that would enable
38
+ # slightly more efficient decryption for AES-SIV)
39
+ #
40
+ # @param message [String] an Encoding::BINARY string to authenticate
41
+ #
42
+ # @return [String] CMAC tag
43
+ def digest(message)
44
+ raise TypeError, "expected String, got #{message.class}" unless message.is_a?(String)
45
+ raise ArgumentError, "message must be Encoding::BINARY" unless message.encoding == Encoding::BINARY
46
+
47
+ if message.empty? || message.length % AES::BLOCK_SIZE != 0
48
+ message = Util.pad(message, AES::BLOCK_SIZE)
49
+ final_block = @key2
50
+ else
51
+ final_block = @key1
52
+ end
53
+
54
+ count = message.length / AES::BLOCK_SIZE
55
+ result = AES::ZERO_BLOCK
56
+
57
+ count.times do |i|
58
+ block = message.slice(AES::BLOCK_SIZE * i, AES::BLOCK_SIZE)
59
+ block = Util.xor(final_block, block) if i == count - 1
60
+ block = Util.xor(block, result)
61
+ result = @cipher.update(block) + @cipher.final
62
+ end
63
+
64
+ result
65
+ end
66
+
67
+ private
68
+
69
+ def _generate_subkeys
70
+ key0 = @cipher.update(AES::ZERO_BLOCK) + @cipher.final
71
+ key1 = Util.dbl(key0)
72
+ key2 = Util.dbl(key1)
73
+ [key1, key2]
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,118 @@
1
+ # encoding: binary
2
+ # frozen_string_literal: true
3
+
4
+ module Miscreant
5
+ module AES
6
+ # The AES-SIV misuse resistant authenticated encryption cipher
7
+ class SIV
8
+ # Generate a new random AES-SIV key of the given size
9
+ #
10
+ # @param size [Integer] size of key in bytes (32 or 64)
11
+ #
12
+ # @return [String] newly generated AES-SIV key
13
+ def self.generate_key(size = 32)
14
+ raise ArgumentError, "key size must be 32 or 64 bytes" unless [32, 64].include?(size)
15
+ SecureRandom.random_bytes(size)
16
+ end
17
+
18
+ # Create a new AES-SIV instance
19
+ #
20
+ # @param key [String] 32-byte or 64-byte Encoding::BINARY cryptographic key
21
+ #
22
+ # @return [Miscreant::AES::SIV] new AES-SIV instance
23
+ def initialize(key)
24
+ raise TypeError, "expected String, got #{key.class}" unless key.is_a?(String)
25
+ raise ArgumentError, "key must be Encoding::BINARY" unless key.encoding == Encoding::BINARY
26
+ raise ArgumentError, "key must be 32 or 64 bytes" unless [32, 64].include?(key.length)
27
+
28
+ length = key.length / 2
29
+
30
+ @mac_key = key.slice(0, length)
31
+ @enc_key = key.slice(length..-1)
32
+ end
33
+
34
+ # Inspect this AES-SIV instance
35
+ #
36
+ # @return [String] description of this instance
37
+ def inspect
38
+ to_s
39
+ end
40
+
41
+ # Encrypt a message using AES-SIV, authenticating it along with the associated data
42
+ #
43
+ # @param plaintext [String] an Encoding::BINARY string to encrypt
44
+ # @param associated_data [Array<String>] optional array of message headers to authenticate
45
+ #
46
+ # @return [String] encrypted ciphertext
47
+ def seal(plaintext, associated_data = [])
48
+ raise TypeError, "expected String, got #{plaintext.class}" unless plaintext.is_a?(String)
49
+ raise ArgumentError, "plaintext must be Encoding::BINARY" unless plaintext.encoding == Encoding::BINARY
50
+
51
+ v = _s2v(associated_data, plaintext)
52
+ ciphertext = _transform(v, plaintext)
53
+ v + ciphertext
54
+ end
55
+
56
+ # Verify and decrypt an AES-SIV ciphertext, authenticating it along with the associated data
57
+ #
58
+ # @param ciphertext [String] an Encoding::BINARY string to decrypt
59
+ # @param associated_data [Array<String>] optional array of message headers to authenticate
60
+ #
61
+ # @raise [Miscreant::IntegrityError] ciphertext and/or associated data are corrupt or tampered with
62
+ # @return [String] decrypted plaintext
63
+ def open(ciphertext, associated_data = [])
64
+ raise TypeError, "expected String, got #{ciphertext.class}" unless ciphertext.is_a?(String)
65
+ raise ArgumentError, "ciphertext must be Encoding::BINARY" unless ciphertext.encoding == Encoding::BINARY
66
+
67
+ v = ciphertext.slice(0, AES::BLOCK_SIZE)
68
+ ciphertext = ciphertext.slice(AES::BLOCK_SIZE..-1)
69
+ plaintext = _transform(v, ciphertext)
70
+
71
+ t = _s2v(associated_data, plaintext)
72
+ raise IntegrityError, "ciphertext verification failure!" unless Util.ct_equal(t, v)
73
+
74
+ plaintext
75
+ end
76
+
77
+ private
78
+
79
+ # Performs raw unauthenticted encryption or decryption of the message
80
+ def _transform(v, data)
81
+ return "".b if data.empty?
82
+
83
+ cipher = OpenSSL::Cipher::AES.new(@mac_key.length * 8, :CTR)
84
+ cipher.encrypt
85
+ cipher.iv = Util.zero_iv_bits(v)
86
+ cipher.key = @enc_key
87
+ cipher.update(data) + cipher.final
88
+ end
89
+
90
+ # The S2V operation consists of the doubling and XORing of the outputs
91
+ # of the pseudo-random function CMAC.
92
+ #
93
+ # See Section 2.4 of RFC 5297 for more information
94
+ def _s2v(associated_data, plaintext)
95
+ # Note: the standalone S2V returns CMAC(1) if the number of passed
96
+ # vectors is zero, however in SIV construction this case is never
97
+ # triggered, since we always pass plaintext as the last vector (even
98
+ # if it's zero-length), so we omit this case.
99
+ cmac = CMAC.new(@mac_key)
100
+ d = cmac.digest(AES::ZERO_BLOCK)
101
+
102
+ associated_data.each do |ad|
103
+ d = Util.dbl(d)
104
+ d = Util.xor(d, cmac.digest(ad))
105
+ end
106
+
107
+ if plaintext.bytesize >= AES::BLOCK_SIZE
108
+ d = Util.xorend(plaintext, d)
109
+ else
110
+ d = Util.dbl(d)
111
+ d = Util.xor(d, Util.pad(plaintext, AES::BLOCK_SIZE))
112
+ end
113
+
114
+ cmac.digest(d)
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,81 @@
1
+ # encoding: binary
2
+ # frozen_string_literal: true
3
+
4
+ module Miscreant
5
+ # Internal utility functions
6
+ module Util
7
+ module_function
8
+
9
+ # Perform a doubling operation as described in the CMAC and SIV papers
10
+ def dbl(value)
11
+ overflow = 0
12
+ words = value.unpack("N4").reverse
13
+
14
+ words.map! do |word|
15
+ new_word = (word << 1) & 0xFFFFFFFF
16
+ new_word |= overflow
17
+ overflow = (word & 0x80000000) >= 0x80000000 ? 1 : 0
18
+ new_word
19
+ end
20
+
21
+ result = words.reverse.pack("N4")
22
+ result[-1] = (result[-1].ord ^ select(overflow, 0x87, 0)).chr
23
+ result
24
+ end
25
+
26
+ # Pad value with a 0x80 value and zeroes up to the given length
27
+ def pad(message, length)
28
+ padded_length = message.length + length - (message.length % length)
29
+ message += "\x80"
30
+ message.ljust(padded_length, "\0")
31
+ end
32
+
33
+ # Perform a constant time(-ish) branch operation
34
+ def select(subject, result_if_one, result_if_zero)
35
+ (~(subject - 1) & result_if_one) | ((subject - 1) & result_if_zero)
36
+ end
37
+
38
+ # Perform an xor on arbitrary bytestrings
39
+ def xor(a, b)
40
+ length = [a.length, b.length].min
41
+ output = "\0" * length
42
+ length.times do |i|
43
+ output[i] = (a[i].ord ^ b[i].ord).chr
44
+ end
45
+ output
46
+ end
47
+
48
+ # XOR the second value into the end of the first
49
+ def xorend(a, b)
50
+ difference = a.length - b.length
51
+
52
+ left = a.slice(0, difference)
53
+ right = a.slice(difference..-1)
54
+
55
+ left + xor(right, b)
56
+ end
57
+
58
+ # Zero out the top bits in the last 32-bit words of the IV
59
+ def zero_iv_bits(iv)
60
+ # "We zero-out the top bit in each of the last two 32-bit words
61
+ # of the IV before assigning it to Ctr"
62
+ # -- http://web.cs.ucdavis.edu/~rogaway/papers/siv.pdf
63
+ iv = iv.dup
64
+ iv[8] = (iv[8].ord & 0x7f).chr
65
+ iv[12] = (iv[12].ord & 0x7f).chr
66
+ iv
67
+ end
68
+
69
+ # Perform a constant time-ish comparison of two bytestrings
70
+ def ct_equal(a, b)
71
+ return false unless a.bytesize == b.bytesize
72
+
73
+ l = a.unpack("C*")
74
+ r = 0
75
+ i = -1
76
+
77
+ b.each_byte { |v| r |= v ^ l[i += 1] }
78
+ r.zero?
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Miscreant
4
+ VERSION = "0.0.0"
5
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ lib = File.expand_path("../lib", __FILE__)
5
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
+ require "miscreant/version"
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = "miscreant"
10
+ spec.version = Miscreant::VERSION
11
+ spec.authors = ["Tony Arcieri"]
12
+ spec.email = ["bascule@gmail.com"]
13
+ spec.licenses = ["MIT"]
14
+ spec.homepage = "https://github.com/miscreant/miscreant/tree/master/ruby/"
15
+ spec.summary = "Misuse-resistant authenticated symmetric encryption"
16
+ spec.description = "Misuse-resistant symmetric encryption using the AES-SIV (RFC 5297) and CHAIN constructions"
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.required_ruby_version = ">= 2.2.2"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.14"
25
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: miscreant
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Tony Arcieri
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-07-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.14'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.14'
27
+ description: Misuse-resistant symmetric encryption using the AES-SIV (RFC 5297) and
28
+ CHAIN constructions
29
+ email:
30
+ - bascule@gmail.com
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - ".gitignore"
36
+ - ".rspec"
37
+ - ".rubocop.yml"
38
+ - ".ruby-version"
39
+ - Gemfile
40
+ - LICENSE.txt
41
+ - README.md
42
+ - Rakefile
43
+ - lib/miscreant.rb
44
+ - lib/miscreant/aes.rb
45
+ - lib/miscreant/aes/cmac.rb
46
+ - lib/miscreant/aes/siv.rb
47
+ - lib/miscreant/util.rb
48
+ - lib/miscreant/version.rb
49
+ - miscreant.gemspec
50
+ homepage: https://github.com/miscreant/miscreant/tree/master/ruby/
51
+ licenses:
52
+ - MIT
53
+ metadata: {}
54
+ post_install_message:
55
+ rdoc_options: []
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 2.2.2
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ requirements: []
69
+ rubyforge_project:
70
+ rubygems_version: 2.6.12
71
+ signing_key:
72
+ specification_version: 4
73
+ summary: Misuse-resistant authenticated symmetric encryption
74
+ test_files: []