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.
- checksums.yaml +4 -4
- data/lib/cyphera/cyphera.rb +36 -6
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a65ed0421e315fb812c18254d76d44e8608fad0968ee2814ae08f2143d52fe1f
|
|
4
|
+
data.tar.gz: 1f365dbd3f2b4394dd86b1e6f37409a49fd346879468871625b47e537edd8a40
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 40e5d3318a64f784bc7b36e74a0e169a249a144dd0c4367423a9f040e17c74a181436e95832754f772469988d3c7adb9b9ad12877b18afea65744ae5d94acc59
|
|
7
|
+
data.tar.gz: fc69eb1257b4841670b84ed3b7a146af687b78cdbc99463627e27b9b25183a96af1792e19f448eba70bde2e7675c5067895e1712ba3b0ca2d61b8304f55ad857
|
data/lib/cyphera/cyphera.rb
CHANGED
|
@@ -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,
|
|
217
|
+
FF3.new(key, tweak, alphabet).encrypt(encryptable)
|
|
189
218
|
when 'ff31'
|
|
190
|
-
FF31.new(key,
|
|
219
|
+
FF31.new(key, tweak, alphabet).encrypt(encryptable)
|
|
191
220
|
else
|
|
192
|
-
FF1.new(key,
|
|
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,
|
|
244
|
+
FF3.new(key, tweak, alphabet).decrypt(encryptable)
|
|
215
245
|
when 'ff31'
|
|
216
|
-
FF31.new(key,
|
|
246
|
+
FF31.new(key, tweak, alphabet).decrypt(encryptable)
|
|
217
247
|
else
|
|
218
|
-
FF1.new(key,
|
|
248
|
+
FF1.new(key, tweak, alphabet).decrypt(encryptable)
|
|
219
249
|
end
|
|
220
250
|
|
|
221
251
|
reinsert_passthroughs(decrypted, positions, chars)
|