cyphera 0.0.1.alpha.6 → 0.0.1.alpha.7

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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/cyphera/cyphera.rb +36 -6
  3. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fd14e187ce2efc327e01b297d3994a7bc4fdad3d403f8e0c3ad8e25454368b51
4
- data.tar.gz: c43eb5a96ee6b4711d1ea7ef49f4690fb7fa1a3e513ff861ee05b7699243b5d4
3
+ metadata.gz: a65ed0421e315fb812c18254d76d44e8608fad0968ee2814ae08f2143d52fe1f
4
+ data.tar.gz: 1f365dbd3f2b4394dd86b1e6f37409a49fd346879468871625b47e537edd8a40
5
5
  SHA512:
6
- metadata.gz: a786d776237f88131028b23335e0326625e8cbfa84502dde2a8fc694b9732739a6046a8e084b21c3ea97385f5821b5ea266ae5a54da23c4e6db037ddf7f15d4c
7
- data.tar.gz: 2dff2617966f49bfb4f438876c942a1c30577723d4e86e68d89be3d80dcb370feaf4fb30fb34649e6d17b6d578b3606ff6079d9cc8f7523dfb8fa4b16caf9b06
6
+ metadata.gz: 40e5d3318a64f784bc7b36e74a0e169a249a144dd0c4367423a9f040e17c74a181436e95832754f772469988d3c7adb9b9ad12877b18afea65744ae5d94acc59
7
+ data.tar.gz: fc69eb1257b4841670b84ed3b7a146af687b78cdbc99463627e27b9b25183a96af1792e19f448eba70bde2e7675c5067895e1712ba3b0ca2d61b8304f55ad857
@@ -107,9 +107,11 @@ module Cyphera
107
107
  end
108
108
 
109
109
  @configurations[name] = {
110
+ 'name' => name,
110
111
  'engine' => cfg.fetch('engine', 'ff1'),
111
112
  'alphabet' => resolve_alphabet(cfg['alphabet']),
112
113
  'key_ref' => cfg['key_ref'],
114
+ 'tweak' => cfg['tweak'],
113
115
  'header' => header,
114
116
  'header_enabled' => header_enabled,
115
117
  'header_length' => cfg.fetch('header_length', 3).to_i,
@@ -176,20 +178,47 @@ module Cyphera
176
178
  $stderr.puts "WARNING: engine 'ff3' is deprecated and cryptographically weak — migrate to 'ff31' (FF3-1)."
177
179
  end
178
180
 
181
+ # Resolve and validate the configuration-level tweak for an FPE engine.
182
+ # FF3 requires exactly 8 bytes and FF3-1 requires exactly 7 — missing
183
+ # → hard error with the canonical spec message; no silent zero-fill.
184
+ # FF1 accepts an empty or arbitrary-length tweak per NIST SP 800-38G.
185
+ def resolve_tweak(configuration)
186
+ raw = configuration['tweak']
187
+ engine = configuration['engine']
188
+ name = configuration['name']
189
+ case engine
190
+ when 'ff3'
191
+ if raw.nil? || raw.empty?
192
+ raise ArgumentError, "configuration '#{name}' is missing required 'tweak' (FF3 needs 8 bytes)"
193
+ end
194
+ [raw].pack('H*')
195
+ when 'ff31'
196
+ if raw.nil? || raw.empty?
197
+ raise ArgumentError, "configuration '#{name}' is missing required 'tweak' (FF3-1 needs 7 bytes)"
198
+ end
199
+ [raw].pack('H*')
200
+ else
201
+ # FF1 — empty tweak is fine, but allow a configured one if supplied.
202
+ return '' if raw.nil? || raw.empty?
203
+ [raw].pack('H*')
204
+ end
205
+ end
206
+
179
207
  def protect_fpe(value, configuration)
180
208
  key = resolve_key(configuration['key_ref'])
181
209
  alphabet = configuration['alphabet']
182
210
  encryptable, positions, chars = extract_passthroughs(value, alphabet)
183
211
  raise ArgumentError, 'no encryptable characters in input' if encryptable.empty?
184
212
 
213
+ tweak = resolve_tweak(configuration)
185
214
  encrypted = case configuration['engine']
186
215
  when 'ff3'
187
216
  warn_ff3_deprecated
188
- FF3.new(key, "\x00" * 8, alphabet).encrypt(encryptable)
217
+ FF3.new(key, tweak, alphabet).encrypt(encryptable)
189
218
  when 'ff31'
190
- FF31.new(key, "\x00" * 7, alphabet).encrypt(encryptable)
219
+ FF31.new(key, tweak, alphabet).encrypt(encryptable)
191
220
  else
192
- FF1.new(key, '', alphabet).encrypt(encryptable)
221
+ FF1.new(key, tweak, alphabet).encrypt(encryptable)
193
222
  end
194
223
 
195
224
  result = reinsert_passthroughs(encrypted, positions, chars)
@@ -208,14 +237,15 @@ module Cyphera
208
237
 
209
238
  encryptable, positions, chars = extract_passthroughs(protected_value, alphabet)
210
239
 
240
+ tweak = resolve_tweak(configuration)
211
241
  decrypted = case configuration['engine']
212
242
  when 'ff3'
213
243
  warn_ff3_deprecated
214
- FF3.new(key, "\x00" * 8, alphabet).decrypt(encryptable)
244
+ FF3.new(key, tweak, alphabet).decrypt(encryptable)
215
245
  when 'ff31'
216
- FF31.new(key, "\x00" * 7, alphabet).decrypt(encryptable)
246
+ FF31.new(key, tweak, alphabet).decrypt(encryptable)
217
247
  else
218
- FF1.new(key, '', alphabet).decrypt(encryptable)
248
+ FF1.new(key, tweak, alphabet).decrypt(encryptable)
219
249
  end
220
250
 
221
251
  reinsert_passthroughs(decrypted, positions, chars)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cyphera
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.alpha.6
4
+ version: 0.0.1.alpha.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Horizon Digital Engineering