miscreant 0.2.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 96a35e90aee3d3f35dcbe9a273e57d9685b7d537
4
- data.tar.gz: dc9ab108d1d8e69daccc528bc6f06f009ab584ed
3
+ metadata.gz: 28739a2b5b206f73877d8c3ecf7d1b90591dbbcb
4
+ data.tar.gz: d044df29dbe78614ef99cded5a1a0a3ccacbfed7
5
5
  SHA512:
6
- metadata.gz: 8463583471437d1be6ef3885bbcee2ef6d78c58db500d2893a2ab3c91e6864eb5669fae96377d59d6a45e4711b6a2b7bbc57bb8d41f1a8538b0475a10ceeeb7e
7
- data.tar.gz: f9d0be51f4255fed217290c9d07e90dea204e3009836bf5088eb861881d3b5f84b0d05804004c48d6b50e21f6367a0b8927177dd7cda138173fd1ef82d4a7039
6
+ metadata.gz: 536b1a5d7b38885783b24d99e19716ab72ea5167684f190ddccb2f5740329c55af95be9782c4f2246eb4b9684e03f0f1329b92abf22d7aee698cb117619eedcc
7
+ data.tar.gz: 4aa49283f01fc63f3b15b77b92b92ce2b98c4888342943355043bb731c915934742319e9e54862f82b25fc163a4b88e82c6304706e9fd6e88a9f256a463c6cb3
data/README.md CHANGED
@@ -1,11 +1,11 @@
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] [![Gitter Chat][gitter-image]][gitter-link]
1
+ # miscreant.rb [![Latest Version][gem-shield]][gem-link] [![Build Status][build-image]][build-link] [![Yard Docs][docs-image]][docs-link] [![MIT licensed][license-image]][license-link] [![Gitter Chat][gitter-image]][gitter-link]
2
2
 
3
3
  [gem-shield]: https://badge.fury.io/rb/miscreant.svg
4
4
  [gem-link]: https://rubygems.org/gems/miscreant
5
5
  [build-image]: https://secure.travis-ci.org/miscreant/miscreant.svg?branch=master
6
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
7
+ [docs-image]: https://img.shields.io/badge/yard-docs-blue.svg
8
+ [docs-link]: http://www.rubydoc.info/gems/miscreant/0.3.0
9
9
  [license-image]: https://img.shields.io/badge/license-MIT-blue.svg
10
10
  [license-link]: https://github.com/miscreant/miscreant/blob/master/LICENSE.txt
11
11
  [gitter-image]: https://badges.gitter.im/badge.svg
@@ -13,9 +13,17 @@
13
13
 
14
14
  > The best crypto you've never heard of, brought to you by [Phil Rogaway]
15
15
 
16
- Ruby implementation of **Miscreant**: Advanced symmetric encryption using the
17
- AES-SIV ([RFC 5297]) and [CHAIN/STREAM] constructions, providing easy-to-use (or
18
- rather, hard-to-misuse) encryption of individual messages or message streams.
16
+ [Phil Rogaway]: https://en.wikipedia.org/wiki/Phillip_Rogaway
17
+
18
+ Ruby implementation of **Miscreant**: Advanced symmetric encryption library
19
+ which provides the [AES-SIV] ([RFC 5297]), [AES-PMAC-SIV], and [STREAM]
20
+ constructions. These algorithms are easy-to-use (or rather, hard-to-misuse)
21
+ and support encryption of individual messages or message streams.
22
+
23
+ [AES-SIV]: https://github.com/miscreant/miscreant/wiki/AES-SIV
24
+ [RFC 5297]: https://tools.ietf.org/html/rfc5297
25
+ [AES-PMAC-SIV]: https://github.com/miscreant/miscreant/wiki/AES-PMAC-SIV
26
+ [STREAM]: https://github.com/miscreant/miscreant/wiki/STREAM
19
27
 
20
28
  **AES-SIV** provides [nonce-reuse misuse-resistance] (NRMR): accidentally
21
29
  reusing a nonce with this construction is not a security catastrophe,
@@ -27,11 +35,7 @@ full plaintext recovery.
27
35
 
28
36
  For more information, see the [toplevel README.md].
29
37
 
30
- [Phil Rogaway]: https://en.wikipedia.org/wiki/Phillip_Rogaway
31
- [AES-SIV]: https://www.iacr.org/archive/eurocrypt2006/40040377/40040377.pdf
32
- [RFC 5297]: https://tools.ietf.org/html/rfc5297
33
- [CHAIN/STREAM]: http://web.cs.ucdavis.edu/~rogaway/papers/oae.pdf
34
- [nonce-reuse misuse-resistance]: https://www.lvh.io/posts/nonce-misuse-resistance-101.html
38
+ [nonce-reuse misuse-resistance]: https://github.com/miscreant/miscreant/wiki/Nonce-Reuse-Misuse-Resistance
35
39
  [AES-GCM]: https://en.wikipedia.org/wiki/Galois/Counter_Mode
36
40
  [chosen ciphertext attacks]: https://en.wikipedia.org/wiki/Chosen-ciphertext_attack
37
41
  [toplevel README.md]: https://github.com/miscreant/miscreant/blob/master/README.md
data/ci.bat ADDED
@@ -0,0 +1 @@
1
+ bundle && bundle exec rake spec
data/ci.sh ADDED
@@ -0,0 +1,6 @@
1
+ #!/bin/bash
2
+
3
+ set -e
4
+
5
+ bundle
6
+ bundle exec rake
@@ -5,11 +5,13 @@ require "openssl"
5
5
  require "securerandom"
6
6
 
7
7
  require "miscreant/version"
8
+
8
9
  require "miscreant/aead"
9
10
  require "miscreant/aes/cmac"
10
11
  require "miscreant/aes/pmac"
11
12
  require "miscreant/aes/siv"
12
13
  require "miscreant/internals"
14
+ require "miscreant/stream"
13
15
 
14
16
  # Miscreant: A misuse-resistant symmetric encryption library
15
17
  module Miscreant
@@ -19,6 +21,9 @@ module Miscreant
19
21
  # Ciphertext failed to verify as authentic
20
22
  IntegrityError = Class.new(CryptoError)
21
23
 
24
+ # Integer value overflowed
25
+ OverflowError = Class.new(StandardError)
26
+
22
27
  # Hide internals from the outside world
23
28
  private_constant :Internals
24
29
  end
@@ -0,0 +1,132 @@
1
+ # encoding: binary
2
+ # frozen_string_literal: true
3
+
4
+ module Miscreant
5
+ # The STREAM online authenticated encryption construction.
6
+ # See <https://eprint.iacr.org/2015/189.pdf> for definition.
7
+ #
8
+ # Miscreant's implementation of STREAM uses an 8-byte (64-bit) nonce
9
+ # prefix along with a 32-bit counter and 1-byte "last block" flag
10
+ module STREAM
11
+ # Size of a nonce required by STREAM in bytes
12
+ NONCE_SIZE = 8
13
+
14
+ # Byte flag indicating this is the last block in the STREAM (otherwise 0)
15
+ LAST_BLOCK_FLAG = 1
16
+
17
+ # Maximum value of the STREAM counter
18
+ COUNTER_MAX = 2**32
19
+
20
+ # Raised if we attempt to continue an already-finished STREAM
21
+ FinishedError = Class.new(StandardError)
22
+
23
+ # A STREAM encryptor
24
+ #
25
+ # This corresponds to the ℰ stream encryptor object as defined in the paper
26
+ # Online Authenticated-Encryption and its Nonce-Reuse Misuse-Resistance
27
+ class Encryptor
28
+ # Create a new STREAM encryptor.
29
+ #
30
+ # @param alg ["AES-SIV", "AES-PMAC-SIV"] cryptographic algorithm to use
31
+ # @param key [String] 32-byte or 64-byte random Encoding::BINARY secret key
32
+ # @param nonce [String] 8-byte nonce
33
+ #
34
+ # @raise [TypeError] nonce is not a String
35
+ # @raise [ArgumentError] nonce is wrong length or not Encoding::BINARY
36
+ def initialize(alg, key, nonce)
37
+ @aead = AEAD.new(alg, key)
38
+ @nonce_encoder = NonceEncoder.new(nonce)
39
+ end
40
+
41
+ # Encrypt the next message in the stream
42
+ #
43
+ # @param plaintext [String] plaintext message to encrypt
44
+ # @param ad [String] (optional) associated data to authenticate
45
+ # @param last_block [true, false] is this the last block in the STREAM?
46
+ #
47
+ # @return [String] ciphertext message
48
+ def seal(plaintext, ad: "", last_block: false)
49
+ @aead.seal(plaintext, nonce: @nonce_encoder.next(last_block), ad: ad)
50
+ end
51
+
52
+ # Inspect this STREAM encryptor instance
53
+ #
54
+ # @return [String] description of this instance
55
+ def inspect
56
+ to_s
57
+ end
58
+ end
59
+
60
+ # A STREAM decryptor
61
+ #
62
+ # This corresponds to the 𝒟 stream decryptor object as defined in the paper
63
+ # Online Authenticated-Encryption and its Nonce-Reuse Misuse-Resistance
64
+ class Decryptor
65
+ # Create a new STREAM decryptor.
66
+ #
67
+ # @param alg ["AES-SIV", "AES-PMAC-SIV"] cryptographic algorithm to use
68
+ # @param key [String] 32-byte or 64-byte random Encoding::BINARY secret key
69
+ # @param nonce [String] 8-byte nonce
70
+ #
71
+ # @raise [TypeError] nonce is not a String
72
+ # @raise [ArgumentError] nonce is wrong length or not Encoding::BINARY
73
+ def initialize(alg, key, nonce)
74
+ @aead = AEAD.new(alg, key)
75
+ @nonce_encoder = NonceEncoder.new(nonce)
76
+ end
77
+
78
+ # Decrypt the next message in the stream
79
+ #
80
+ # @param ciphertext [String] cipher message to encrypt
81
+ # @param ad [String] (optional) associated data to authenticate
82
+ # @param last_block [true, false] is this the last block in the STREAM?
83
+ #
84
+ # @raise [Miscreant::IntegrityError] ciphertext and/or associated data are corrupt or tampered with
85
+ # @return [String] plaintext message
86
+ def open(ciphertext, ad: "", last_block: false)
87
+ @aead.open(ciphertext, nonce: @nonce_encoder.next(last_block), ad: ad)
88
+ end
89
+
90
+ # Inspect this STREAM encryptor instance
91
+ #
92
+ # @return [String] description of this instance
93
+ def inspect
94
+ to_s
95
+ end
96
+ end
97
+
98
+ # Computes STREAM nonces based on the current position in the STREAM.
99
+ class NonceEncoder
100
+ # Create a new nonce encoder with the given prefix
101
+ #
102
+ # @param [nonce_prefix] 64-bit string used as the STREAM nonce prefix
103
+ #
104
+ # @raise [TypeError] nonce prefix is not a String
105
+ # @raise [ArgumentError] nonce prefix is wrong length or not Encoding::BINARY
106
+ def initialize(nonce_prefix)
107
+ Internals::Util.validate_bytestring("nonce", nonce_prefix, length: NONCE_SIZE)
108
+ @nonce_prefix = nonce_prefix
109
+ @counter = 0
110
+ @finished = false
111
+ end
112
+
113
+ # Obtain the next nonce in the stream
114
+ #
115
+ # @param last_block [true, false] is this the last block?
116
+ #
117
+ # @return [String] encoded STREAM nonce
118
+ def next(last_block)
119
+ raise FinishedError, "STREAM is already finished" if @finished
120
+ @finished = last_block
121
+
122
+ encoded_nonce = [@nonce_prefix, @counter, last_block ? LAST_BLOCK_FLAG : 0].pack("a8NC")
123
+ @counter += 1
124
+ raise OverflowError, "STREAM counter overflowed" if @counter >= COUNTER_MAX
125
+
126
+ encoded_nonce
127
+ end
128
+ end
129
+
130
+ private_constant :NonceEncoder
131
+ end
132
+ end
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Miscreant
5
- VERSION = "0.2.0"
5
+ VERSION = "0.3.0"
6
6
  end
@@ -11,8 +11,8 @@ Gem::Specification.new do |spec|
11
11
  spec.email = ["bascule@gmail.com"]
12
12
  spec.summary = "Misuse-resistant authenticated symmetric encryption"
13
13
  spec.description = <<-DESCRIPTION.strip.gsub(/\s+/, " ")
14
- Misuse-resistant symmetric encryption using the AES-SIV (RFC 5297)
15
- and CHAIN/STREAM constructions.
14
+ Misuse resistant symmetric encryption library providing AES-SIV (RFC 5297),
15
+ AES-PMAC-SIV, and STREAM constructions
16
16
  DESCRIPTION
17
17
 
18
18
  spec.version = Miscreant::VERSION
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: miscreant
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony Arcieri
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-10-02 00:00:00.000000000 Z
11
+ date: 2017-12-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,6 +38,8 @@ files:
38
38
  - Gemfile
39
39
  - README.md
40
40
  - Rakefile
41
+ - ci.bat
42
+ - ci.sh
41
43
  - lib/miscreant.rb
42
44
  - lib/miscreant/aead.rb
43
45
  - lib/miscreant/aes/cmac.rb
@@ -48,6 +50,7 @@ files:
48
50
  - lib/miscreant/internals/aes/ctr.rb
49
51
  - lib/miscreant/internals/block.rb
50
52
  - lib/miscreant/internals/util.rb
53
+ - lib/miscreant/stream.rb
51
54
  - lib/miscreant/version.rb
52
55
  - miscreant.gemspec
53
56
  homepage: https://github.com/miscreant/miscreant/tree/master/ruby/
@@ -70,7 +73,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
70
73
  version: '0'
71
74
  requirements: []
72
75
  rubyforge_project:
73
- rubygems_version: 2.6.12
76
+ rubygems_version: 2.6.13
74
77
  signing_key:
75
78
  specification_version: 4
76
79
  summary: Misuse-resistant authenticated symmetric encryption