miscreant 0.0.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.
@@ -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: []