rubyment 0.5.25438564 → 0.5.25471659
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/rubyment.rb +416 -12
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 048e8eae5ac557122a9a5e74a3019c29768cf1c5
|
4
|
+
data.tar.gz: 7ad419465aab2718f75be44c706f435a326313ab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 218c7e8b2b10503986b12b7a0d0b0411f4dfb9c910614b8535e9608241884bbe57efbd0cb558347c057d4bf3580a6dd6e1fcc719ed0d8288bd84f86eda17deba
|
7
|
+
data.tar.gz: 398b1b171d911c3f79e9040e05e10429f34265690b3749acd44ec32aaa757ce380dfd6ff768c872599d6a8bff2af1804a7ed6ad5ee600b0382bdbc138a994aa8
|
data/lib/rubyment.rb
CHANGED
@@ -67,8 +67,9 @@ class Rubyment
|
|
67
67
|
:home_dir => Dir.home,
|
68
68
|
:system_user => ENV['USER'] || ENV['USERNAME'],
|
69
69
|
:system_user_is_super => ENV['USER'] == "root", # changed plan: platform indenpend.
|
70
|
-
:static_separator_key => "
|
71
|
-
:static_end_key => "
|
70
|
+
:static_separator_key => "strings_having_this" + "_string_not_guaranteed_to_work",
|
71
|
+
:static_end_key => "strings_havinng_this_string" + "_also_not_guaranteed_to_work",
|
72
|
+
:static_separator_key_per_execution => "strings_having_this" + "_string_not_guaranteed_to_work" + (Proc.new {}).to_s + Time.now.to_s,
|
72
73
|
}
|
73
74
|
@memory.update memory.to_h
|
74
75
|
invoke @memory[:invoke].to_a
|
@@ -138,6 +139,11 @@ class Rubyment
|
|
138
139
|
end
|
139
140
|
|
140
141
|
|
142
|
+
# returns a string having the current backtrace, for debugging.
|
143
|
+
def backtrace
|
144
|
+
Thread.current.backtrace.join("\n")
|
145
|
+
end
|
146
|
+
|
141
147
|
# returns a Class object out of class_name (or itself if it is already
|
142
148
|
# a class)
|
143
149
|
def to_class args=ARGV
|
@@ -236,6 +242,24 @@ class Rubyment
|
|
236
242
|
end
|
237
243
|
|
238
244
|
|
245
|
+
# returns the contents of file.
|
246
|
+
# file can be a url, if 'open-uri' is available.
|
247
|
+
# can throw exceptions
|
248
|
+
def file_or_url_contents file
|
249
|
+
contents = nil
|
250
|
+
stderr = @memory[:stderr]
|
251
|
+
(require 'open-uri') && open_uri = true
|
252
|
+
require 'fileutils'
|
253
|
+
file = file.to_s
|
254
|
+
file_is_filename = true
|
255
|
+
open_uri && (
|
256
|
+
contents = open(file).read
|
257
|
+
) || (
|
258
|
+
contents = File.read
|
259
|
+
)
|
260
|
+
contents
|
261
|
+
end
|
262
|
+
|
239
263
|
# returns the contents of file (or empty, or a default
|
240
264
|
# if a second parameter is given).
|
241
265
|
# if file is a nonexisting filepath, or by any reason
|
@@ -278,6 +302,8 @@ class Rubyment
|
|
278
302
|
|
279
303
|
|
280
304
|
# opens an echoing prompt, if arg1 is nil or empty
|
305
|
+
# not prepared to work with binary input (which can contain \0)
|
306
|
+
# closed for extensions
|
281
307
|
# args:
|
282
308
|
# [ arg1 (String or nil)]
|
283
309
|
def input_single_line args=ARGV
|
@@ -289,6 +315,8 @@ class Rubyment
|
|
289
315
|
|
290
316
|
|
291
317
|
# opens a non-echoing prompt, if arg1 is nil or empty
|
318
|
+
# not prepared to work with binary input (which can contain \0)
|
319
|
+
# closed for extensions
|
292
320
|
# args:
|
293
321
|
# [ arg1 (String or nil)]
|
294
322
|
def input_single_line_non_echo args=ARGV
|
@@ -301,6 +329,8 @@ class Rubyment
|
|
301
329
|
|
302
330
|
|
303
331
|
# opens an echoing multiline prompt, if arg1 is nil or empty
|
332
|
+
# not prepared to work with binary input (which can contain \0)
|
333
|
+
# closed for extensions
|
304
334
|
# args:
|
305
335
|
# [ arg1 (String or nil)]
|
306
336
|
def input_multi_line args=ARGV
|
@@ -312,6 +342,8 @@ class Rubyment
|
|
312
342
|
|
313
343
|
|
314
344
|
# opens a non-echoing multiline prompt, if arg1 is nil or empty
|
345
|
+
# not prepared to work with binary input (which can contain \0)
|
346
|
+
# closed for extensions
|
315
347
|
# args:
|
316
348
|
# [ arg1 (String or nil)]
|
317
349
|
def input_multi_line_non_echo args=ARGV
|
@@ -323,6 +355,62 @@ class Rubyment
|
|
323
355
|
end
|
324
356
|
|
325
357
|
|
358
|
+
# opens an echoing prompt, if arg1 is nil or empty
|
359
|
+
# better prepared to work with binary input
|
360
|
+
# args:
|
361
|
+
# [ arg1 (String or nil)]
|
362
|
+
def binary_input_single_line args=ARGV
|
363
|
+
stderr = @memory[:stderr]
|
364
|
+
stdin = @memory[:stdin]
|
365
|
+
stderr.print "single line:"
|
366
|
+
static_separator_key_per_execution = @memory[:static_separator_key_per_execution]
|
367
|
+
args.shift.to_s.b.split(static_separator_key_per_execution).first || stdin.gets.chomp
|
368
|
+
end
|
369
|
+
|
370
|
+
|
371
|
+
# opens a non-echoing prompt, if arg1 is nil or empty
|
372
|
+
# better prepared to work with binary input (which can contain \0)
|
373
|
+
# args:
|
374
|
+
# [ arg1 (String or nil)]
|
375
|
+
def binary_input_single_line_non_echo args=ARGV
|
376
|
+
stderr = @memory[:stderr]
|
377
|
+
stdin = @memory[:stdin]
|
378
|
+
static_separator_key_per_execution = @memory[:static_separator_key_per_execution]
|
379
|
+
require "io/console"
|
380
|
+
stderr.print "non echo single line:"
|
381
|
+
args.shift.to_s.b.split(static_separator_key_per_execution).first || stdin.noecho{ stdin.gets}.chomp
|
382
|
+
end
|
383
|
+
|
384
|
+
|
385
|
+
# opens an echoing multiline prompt, if arg1 is nil or empty
|
386
|
+
# better prepared to work with binary input
|
387
|
+
# args:
|
388
|
+
# [ arg1 (String or nil)]
|
389
|
+
def binary_input_multi_line args=ARGV
|
390
|
+
stderr = @memory[:stderr]
|
391
|
+
stdin = @memory[:stdin]
|
392
|
+
static_separator_key_per_execution = @memory[:static_separator_key_per_execution]
|
393
|
+
stderr.print "multiline[enter + control-D to stop]:"
|
394
|
+
args.shift.to_s.b.split(static_separator_key_per_execution).first || stdin.readlines.join
|
395
|
+
end
|
396
|
+
|
397
|
+
|
398
|
+
# opens a non-echoing multiline prompt, if arg1 is nil or empty
|
399
|
+
# better prepared to work with binary input (which can contain \0)
|
400
|
+
# args:
|
401
|
+
# [ arg1 (String or nil)]
|
402
|
+
def binary_input_multi_line_non_echo args=ARGV
|
403
|
+
stderr = @memory[:stderr]
|
404
|
+
stdin = @memory[:stdin]
|
405
|
+
static_separator_key_per_execution = @memory[:static_separator_key_per_execution]
|
406
|
+
require "io/console"
|
407
|
+
# puts backtrace
|
408
|
+
# p args.map {|e| e.to_s[0..15] }
|
409
|
+
stderr.print "multiline[enter + control-D to stop]:"
|
410
|
+
args.shift.to_s.b.split(static_separator_key_per_execution).first || stdin.noecho{ stdin.readlines}.join.chomp
|
411
|
+
end
|
412
|
+
|
413
|
+
|
326
414
|
def input_shift_or_empty_string args=ARGV, default = ''
|
327
415
|
args.shift || default
|
328
416
|
end
|
@@ -440,6 +528,7 @@ class Rubyment
|
|
440
528
|
# +ending+:: [nil] deprecated
|
441
529
|
# +base64_salt+:: [String, nil] #generate_pbkdf2_key salt encoded with Base64
|
442
530
|
# +base64_iter+:: [String, nil] #generate_pbkdf2_key iterations encoded with Base64
|
531
|
+
# +data_not_base64+:: [true, false, nil] don't return base64 data -- the same +data_not_base64+ given for enc should be used.
|
443
532
|
#
|
444
533
|
# @return [String] decoded data
|
445
534
|
def dec args=ARGV
|
@@ -447,7 +536,7 @@ class Rubyment
|
|
447
536
|
require 'base64'
|
448
537
|
memory = @memory
|
449
538
|
static_end_key = memory[:static_end_key]
|
450
|
-
password, base64_iv, base64_encrypted, ending, base64_salt, base64_iter = args
|
539
|
+
password, base64_iv, base64_encrypted, ending, base64_salt, base64_iter, data_not_base64 = args
|
451
540
|
salt = Base64.decode64 base64_salt
|
452
541
|
iter = Base64.decode64 base64_iter
|
453
542
|
ending = ending.to_s.split("\0").first || static_end_key
|
@@ -461,7 +550,8 @@ class Rubyment
|
|
461
550
|
|
462
551
|
decipher.key = key || (Digest::SHA256.hexdigest password)
|
463
552
|
decipher.iv = Base64.decode64 base64_iv
|
464
|
-
|
553
|
+
base64_plain = decipher.update(Base64.decode64 base64_encrypted) + decipher.final
|
554
|
+
plain = data_not_base64 && (Base64.decode64 base64_plain) || base64_plain
|
465
555
|
# split is not the ideal, if ever ending is duplicated it won't
|
466
556
|
# work. also may be innefficient.
|
467
557
|
(plain.split ending).first
|
@@ -550,6 +640,8 @@ class Rubyment
|
|
550
640
|
|
551
641
|
# encode data into aes-128-cbc cipher protected by a key generated
|
552
642
|
# by #generate_pbkdf2_key, using given +password+, +salt+, +iter+
|
643
|
+
# By default, may not work with binary data. Set +data_not_base64+ to
|
644
|
+
# true (or give data already as base64) to make it work.
|
553
645
|
#
|
554
646
|
# @param [Array] args, an +Array+ whose elements are expected to be:
|
555
647
|
# +password+:: [String, nil] password to be used to encryption.
|
@@ -557,6 +649,7 @@ class Rubyment
|
|
557
649
|
# +ending+:: [nil] deprecated
|
558
650
|
# +salt+:: [String, nil] #generate_pbkdf2_key salt argument
|
559
651
|
# +iter+:: [String, nil] #generate_pbkdf2_key iterations argument
|
652
|
+
# +data_not_base64+:: [true, false, nil] data not yet in base64
|
560
653
|
#
|
561
654
|
# @return @param [Array] an +Array+ whose elements are expected to be:
|
562
655
|
# +base64_encrypted+:: [String, nil] ciphered data (without metadata) encoded with Base64
|
@@ -570,7 +663,7 @@ class Rubyment
|
|
570
663
|
require 'base64'
|
571
664
|
memory = @memory
|
572
665
|
static_end_key = memory[:static_end_key]
|
573
|
-
password, data, ending, salt, iter = args
|
666
|
+
password, data, ending, salt, iter, data_not_base64 = args
|
574
667
|
ending ||= static_end_key
|
575
668
|
key, password, salt, iter = (
|
576
669
|
generate_pbkdf2_key [password, salt, iter]
|
@@ -581,7 +674,8 @@ class Rubyment
|
|
581
674
|
|
582
675
|
cipher.key = key || (Digest::SHA256.hexdigest password)
|
583
676
|
iv = cipher.random_iv
|
584
|
-
|
677
|
+
base64_data = data_not_base64 && (Base64.encode64 data) || data
|
678
|
+
encrypted = cipher.update(base64_data + ending) + cipher.final
|
585
679
|
|
586
680
|
base64_iv = Base64.encode64 iv
|
587
681
|
base64_encrypted = Base64.encode64 encrypted
|
@@ -776,15 +870,16 @@ class Rubyment
|
|
776
870
|
# echo) from @memory[:stdin], which defaults to STDIN
|
777
871
|
# * +password+ [String, nil] password to be used to encryption.
|
778
872
|
# If empty or nil, read (without echo) from @memory[:stdin], which defaults to STDIN
|
873
|
+
# +data_not_base64+:: [true, false, nil] don't return base64 data -- the same +data_not_base64+ given for enc should be used.
|
779
874
|
#
|
780
875
|
# @return [TrueClass, FalseClass] depending on whether test succeeds.
|
781
876
|
def dec_interactive args=ARGV
|
782
877
|
stderr = @memory[:stderr]
|
783
|
-
iv, encrypted, base64_salt, base64_iter, password = args
|
878
|
+
iv, encrypted, base64_salt, base64_iter, password, data_not_base64 = args
|
784
879
|
stderr.print "[password]"
|
785
880
|
password = (input_single_line_non_echo [password])
|
786
881
|
stderr.puts
|
787
|
-
dec [password, iv, encrypted, nil, base64_salt, base64_iter]
|
882
|
+
dec [password, iv, encrypted, nil, base64_salt, base64_iter, data_not_base64]
|
788
883
|
end
|
789
884
|
|
790
885
|
|
@@ -839,7 +934,7 @@ class Rubyment
|
|
839
934
|
stderr.puts "# programmatically:"
|
840
935
|
stderr.puts "dec " + dec_args.to_s
|
841
936
|
stderr.puts "# shell: "
|
842
|
-
stderr.puts "
|
937
|
+
stderr.puts "#{$0} invoke_double p dec " + (output_array_to_shell dec_args).to_s
|
843
938
|
data_plain = dec [password, base64_iv, base64_encrypted, nil, base64_salt, base64_iter]
|
844
939
|
judgement =
|
845
940
|
[
|
@@ -848,18 +943,60 @@ class Rubyment
|
|
848
943
|
end
|
849
944
|
|
850
945
|
|
946
|
+
# output encrypted data (and data required to
|
947
|
+
# decrypt) into encrypted_base64_filename
|
948
|
+
def output_enc_file args=ARGV
|
949
|
+
stderr = @memory[:stderr]
|
950
|
+
require 'json'
|
951
|
+
require 'base64'
|
952
|
+
base64_iv, base64_encrypted, base64_salt, base64_iter, encrypted_base64_filename = args
|
953
|
+
metadata = {
|
954
|
+
"metadata" => "Metadata",
|
955
|
+
"base64_iv" => base64_iv,
|
956
|
+
"base64_encrypted" => base64_encrypted,
|
957
|
+
"base64_salt" => base64_salt,
|
958
|
+
"base64_iter" => base64_iter,
|
959
|
+
}
|
960
|
+
base64_json_serialized_data = Base64.encode64 JSON.pretty_generate metadata
|
961
|
+
File.write encrypted_base64_filename, base64_json_serialized_data
|
962
|
+
stderr.puts "# File written: \n# #{encrypted_base64_filename}"
|
963
|
+
end
|
964
|
+
|
965
|
+
|
966
|
+
# output encrypted data (and data required to
|
967
|
+
# decrypt) into encrypted_base64_filename
|
968
|
+
def output_dec_file args=ARGV
|
969
|
+
stderr = @memory[:stderr]
|
970
|
+
require 'json'
|
971
|
+
require 'base64'
|
972
|
+
enc_filename_or_url, out_filename, password, data_is_base64 = args
|
973
|
+
base64_json_serialized_data = file_or_url_contents enc_filename_or_url
|
974
|
+
|
975
|
+
metadata = JSON.parse Base64.decode64 base64_json_serialized_data
|
976
|
+
base64_iv = metadata["base64_iv"]
|
977
|
+
base64_encrypted = metadata["base64_encrypted"]
|
978
|
+
base64_salt = metadata["base64_salt"]
|
979
|
+
base64_iter = metadata["base64_iter"]
|
980
|
+
base64_key = metadata["base64_key" ]
|
981
|
+
ending = nil
|
982
|
+
pw_plain = binary_dec [password, base64_iv, base64_encrypted, ending, base64_salt, base64_iter, data_is_base64]
|
983
|
+
File.write out_filename, pw_plain
|
984
|
+
stderr.puts "# File written: \n# #{out_filename}"
|
985
|
+
end
|
986
|
+
|
987
|
+
|
851
988
|
# test for enc and dec_interactive.
|
852
989
|
# good idea is to use this function once with the desired
|
853
990
|
# data, password, and use the stderr output
|
854
991
|
def test__enc_dec_interactive args=ARGV
|
855
992
|
stderr = @memory[:stderr]
|
856
|
-
data, password = args
|
993
|
+
data, password, encrypted_base64_filename, data_not_base64 = args
|
857
994
|
stderr.print "[data]"
|
858
995
|
data = input_multi_line_non_echo [data]
|
859
996
|
stderr.print "[password]"
|
860
997
|
password = input_single_line_non_echo [password]
|
861
998
|
stderr.puts
|
862
|
-
base64_encrypted, base64_iv, base64_salt, base64_iter, base64_key = enc [password, data]
|
999
|
+
base64_encrypted, base64_iv, base64_salt, base64_iter, base64_key = enc [password, data, nil, nil, nil, data_not_base64 ]
|
863
1000
|
# the output is supposed to be safe to store,
|
864
1001
|
# so password is not placed in from dec_interactive_args:
|
865
1002
|
dec_interactive_args = [base64_iv, base64_encrypted, base64_salt, base64_iter]
|
@@ -869,7 +1006,8 @@ class Rubyment
|
|
869
1006
|
stderr.puts "#{$0} invoke_double puts dec_interactive " + (output_array_to_shell dec_interactive_args).to_s
|
870
1007
|
stderr.puts "#or shell var:"
|
871
1008
|
stderr.puts "my_secret=$(#{$0} invoke_double puts dec_interactive " + (output_array_to_shell dec_interactive_args).to_s + ")\necho $my_secret\nunset mysecret"
|
872
|
-
|
1009
|
+
encrypted_base64_filename && output_enc_file(dec_interactive_args + [encrypted_base64_filename])
|
1010
|
+
data_plain = dec_interactive(dec_interactive_args + [password, data_not_base64])
|
873
1011
|
judgement =
|
874
1012
|
[
|
875
1013
|
[data, data_plain, "data"]
|
@@ -877,6 +1015,272 @@ class Rubyment
|
|
877
1015
|
end
|
878
1016
|
|
879
1017
|
|
1018
|
+
# similar to
|
1019
|
+
# test__enc_dec_interactive,
|
1020
|
+
# just that the data is ready from a file instead
|
1021
|
+
# note that there is an extra argument between
|
1022
|
+
# the args, the enc_out_filename.
|
1023
|
+
def test__enc_dec_file_interactive args=ARGV
|
1024
|
+
stderr = @memory[:stderr]
|
1025
|
+
filename_or_url, enc_out_filename, password, data_not_base64 = args
|
1026
|
+
stderr.print "[filename_or_url]"
|
1027
|
+
filename_or_url = input_multi_line_non_echo [filename_or_url]
|
1028
|
+
stderr.print "[output_filename_encrypted_data]"
|
1029
|
+
enc_out_filename = input_multi_line_non_echo [enc_out_filename ]
|
1030
|
+
data = file_or_url_contents filename_or_url
|
1031
|
+
test__enc_dec_interactive [ data, password, enc_out_filename, data_not_base64 ]
|
1032
|
+
end
|
1033
|
+
|
1034
|
+
|
1035
|
+
# basically the reverse of test__enc_dec_file_interactive
|
1036
|
+
# planned improvements: still outputs to stdout
|
1037
|
+
def test__dec_file_interactive args=ARGV
|
1038
|
+
stderr = @memory[:stderr]
|
1039
|
+
enc_filename_or_url, out_filename, password, data_not_base64 = args
|
1040
|
+
stderr.print "[enc_filename_or_url]"
|
1041
|
+
enc_filename_or_url = input_multi_line_non_echo [enc_filename_or_url]
|
1042
|
+
stderr.print "[output_filename_plain_data]"
|
1043
|
+
out_filename = input_multi_line_non_echo [out_filename ]
|
1044
|
+
stderr.print "[password]"
|
1045
|
+
password = input_single_line_non_echo [password]
|
1046
|
+
data = file_or_url_contents enc_filename_or_url
|
1047
|
+
require 'json'
|
1048
|
+
require 'base64'
|
1049
|
+
base64_json_serialized_data = data
|
1050
|
+
metadata = JSON.parse Base64.decode64 base64_json_serialized_data
|
1051
|
+
base64_iv = metadata["base64_iv"]
|
1052
|
+
base64_encrypted = metadata["base64_encrypted"]
|
1053
|
+
base64_salt = metadata["base64_salt"]
|
1054
|
+
base64_iter = metadata["base64_iter"]
|
1055
|
+
base64_key = metadata["base64_key" ]
|
1056
|
+
ending = nil
|
1057
|
+
pw_plain = dec [password, base64_iv, base64_encrypted, ending, base64_salt, base64_iter, data_not_base64]
|
1058
|
+
shell_dec_output [pw_plain]
|
1059
|
+
end
|
1060
|
+
|
1061
|
+
|
1062
|
+
# encode data into aes-128-cbc cipher protected by a key generated
|
1063
|
+
# by #generate_pbkdf2_key, using given +password+, +salt+, +iter+
|
1064
|
+
# By default, must work with binary data. Set +data_is_base64+ to
|
1065
|
+
# true (or give data already as base64) to achieve the original
|
1066
|
+
# behavior of enc(), and avoid one encoding operation on data.
|
1067
|
+
#
|
1068
|
+
# @param [Array] args, an +Array+ whose elements are expected to be:
|
1069
|
+
# +password+:: [String, nil] password to be used to encryption.
|
1070
|
+
# +data+:: [String, nil] data to be encoded data
|
1071
|
+
# +ending+:: [nil] deprecated
|
1072
|
+
# +salt+:: [String, nil] #generate_pbkdf2_key salt argument
|
1073
|
+
# +iter+:: [String, nil] #generate_pbkdf2_key iterations argument
|
1074
|
+
# +data_is_base64+:: [true, false, nil] data already in base64
|
1075
|
+
#
|
1076
|
+
#
|
1077
|
+
# @return @param [Array] an +Array+ whose elements are expected to be:
|
1078
|
+
# +base64_encrypted+:: [String, nil] ciphered data (without metadata) encoded with Base64
|
1079
|
+
# +base64_iv+:: [String] initialization vectors encoded with Base64
|
1080
|
+
# +base64_salt+:: [String] #generate_pbkdf2_key salt encoded with Base64
|
1081
|
+
# +base64_iter+:: [String] #generate_pbkdf2_key iterations encoded with Base64
|
1082
|
+
# +base64_key+:: [String] #generate_pbkdf2_key return value
|
1083
|
+
#
|
1084
|
+
def binary_enc args=ARGV
|
1085
|
+
require 'openssl'
|
1086
|
+
require 'base64'
|
1087
|
+
memory = @memory
|
1088
|
+
static_end_key = memory[:static_end_key] + "_binary"
|
1089
|
+
password, data, ending, salt, iter, data_is_base64 = args
|
1090
|
+
ending ||= static_end_key
|
1091
|
+
key, password, salt, iter = (
|
1092
|
+
generate_pbkdf2_key [password, salt, iter]
|
1093
|
+
)|| [nil, password, salt, iter]
|
1094
|
+
|
1095
|
+
cipher = OpenSSL::Cipher.new('aes-128-cbc')
|
1096
|
+
cipher.encrypt
|
1097
|
+
|
1098
|
+
cipher.key = key || (Digest::SHA256.hexdigest password)
|
1099
|
+
iv = cipher.random_iv
|
1100
|
+
base64_data = data_is_base64 && (Base64.encode64 data) || data
|
1101
|
+
encrypted = cipher.update(base64_data + ending) + cipher.final
|
1102
|
+
|
1103
|
+
base64_iv = Base64.encode64 iv
|
1104
|
+
base64_encrypted = Base64.encode64 encrypted
|
1105
|
+
base64_salt = Base64.encode64 salt.to_s
|
1106
|
+
base64_iter = Base64.encode64 iter.to_s
|
1107
|
+
base64_key = Base64.encode64 key.to_s
|
1108
|
+
|
1109
|
+
[base64_encrypted, base64_iv, base64_salt, base64_iter, base64_key]
|
1110
|
+
end
|
1111
|
+
|
1112
|
+
|
1113
|
+
# decipher the data encoded by binary_enc
|
1114
|
+
#
|
1115
|
+
# @param [Array] args, an +Array+ whose elements are expected to be:
|
1116
|
+
# +password+:: [String, nil] password to be used to encryption.
|
1117
|
+
# +base64_iv+:: [String, nil] initialization vectors encoded with Base64
|
1118
|
+
# +base64_encrypted+:: [String, nil] ciphered data (without metadata) encoded with Base64
|
1119
|
+
# +ending+:: [nil] deprecated
|
1120
|
+
# +base64_salt+:: [String, nil] #generate_pbkdf2_key salt encoded with Base64
|
1121
|
+
# +base64_iter+:: [String, nil] #generate_pbkdf2_key iterations encoded with Base64
|
1122
|
+
# +data_is_base64+:: [true, false, nil] return base64 data -- the same +data_is_base64+ given for enc should be used.
|
1123
|
+
#
|
1124
|
+
# @return [String] decoded data
|
1125
|
+
def binary_dec args=ARGV
|
1126
|
+
require 'openssl'
|
1127
|
+
require 'base64'
|
1128
|
+
memory = @memory
|
1129
|
+
static_end_key = memory[:static_end_key] + "_binary"
|
1130
|
+
password, base64_iv, base64_encrypted, ending, base64_salt, base64_iter, data_is_base64 = args
|
1131
|
+
salt = Base64.decode64 base64_salt
|
1132
|
+
iter = Base64.decode64 base64_iter
|
1133
|
+
# FIXME: don't split on \0
|
1134
|
+
ending = ending.to_s.split("\0").first || static_end_key
|
1135
|
+
key, password, salt, iter = (
|
1136
|
+
generate_pbkdf2_key [password, salt, iter]
|
1137
|
+
)|| [nil, password, salt, iter]
|
1138
|
+
|
1139
|
+
decipher = OpenSSL::Cipher.new('aes-128-cbc')
|
1140
|
+
decipher.decrypt
|
1141
|
+
decipher.padding = 0
|
1142
|
+
|
1143
|
+
decipher.key = key || (Digest::SHA256.hexdigest password)
|
1144
|
+
decipher.iv = Base64.decode64 base64_iv
|
1145
|
+
base64_plain = decipher.update(Base64.decode64 base64_encrypted) + decipher.final
|
1146
|
+
plain = data_is_base64 && (Base64.decode64 base64_plain) || base64_plain
|
1147
|
+
# split is not the ideal, if ever ending is duplicated it won't
|
1148
|
+
# work. also may be innefficient.
|
1149
|
+
(plain.split ending).first
|
1150
|
+
|
1151
|
+
end
|
1152
|
+
|
1153
|
+
|
1154
|
+
# an alternative interface to binary_dec -- reads password if
|
1155
|
+
# nil or empty.
|
1156
|
+
#
|
1157
|
+
# @param [Array] args Defaults to +ARGV+. Elements:
|
1158
|
+
# * +data+ [String, nil] data to be encrypted, If empty or nil, read (without
|
1159
|
+
# echo) from @memory[:stdin], which defaults to STDIN
|
1160
|
+
# * +password+ [String, nil] password to be used to encryption.
|
1161
|
+
# If empty or nil, read (without echo) from @memory[:stdin], which defaults to STDIN
|
1162
|
+
# +data_is_base64+:: [true, false, nil] return base64 data -- the same +data_is_base64+ given for enc should be used.
|
1163
|
+
#
|
1164
|
+
# @return [TrueClass, FalseClass] depending on whether test succeeds.
|
1165
|
+
def binary_dec_interactive args=ARGV
|
1166
|
+
stderr = @memory[:stderr]
|
1167
|
+
iv, encrypted, base64_salt, base64_iter, password, data_is_base64 = args
|
1168
|
+
stderr.print "[password]"
|
1169
|
+
password = (input_single_line_non_echo [password])
|
1170
|
+
stderr.puts
|
1171
|
+
binary_dec [password, iv, encrypted, nil, base64_salt, base64_iter, data_is_base64]
|
1172
|
+
end
|
1173
|
+
|
1174
|
+
|
1175
|
+
# test for binary_enc and binary_dec.
|
1176
|
+
# "" and nil are expected to be treated
|
1177
|
+
# as the same.
|
1178
|
+
def test__binary_enc_dec_nil args=ARGV
|
1179
|
+
nil_case = binary_dec [nil, "ltUQIxgRAeUNXPNTTps8FQ==\n", "xyeqxw/TzkyXtOxpDqAl58SNAvXPyNZ89B5JGtwDkcbjo0vObgPsh5FrgZJs\nHPjofsyXnljnTrHpDoQeDVezo9wBZ74NU+TSi/GssX605oE=\n", nil, "TU4o3IKiFWki3rZ3lMchLQ==\n", "MjAwMDA=\n"]
|
1180
|
+
empty = binary_dec ["", "ltUQIxgRAeUNXPNTTps8FQ==\n", "xyeqxw/TzkyXtOxpDqAl58SNAvXPyNZ89B5JGtwDkcbjo0vObgPsh5FrgZJs\nHPjofsyXnljnTrHpDoQeDVezo9wBZ74NU+TSi/GssX605oE=\n", "", "TU4o3IKiFWki3rZ3lMchLQ==\n", "MjAwMDA=\n"]
|
1181
|
+
judgement =
|
1182
|
+
[
|
1183
|
+
[nil_case, empty, "empty_nil_equality"]
|
1184
|
+
].map(&method("expect_equal")).all?
|
1185
|
+
end
|
1186
|
+
|
1187
|
+
|
1188
|
+
# test for binary_enc and binary_dec.
|
1189
|
+
#
|
1190
|
+
# @param [Array] args, an +Array+ whose elements are expected to be:
|
1191
|
+
# +data+:: [String, nil] data to be encrypted.
|
1192
|
+
# If empty or nil, read (without echo) from @memory[:stdin], which defaults to STDIN
|
1193
|
+
# +password+:: [String, nil] password to be used to encryption.
|
1194
|
+
# If empty or nil, read (without echo) from @memory[:stdin], which defaults to STDIN
|
1195
|
+
#
|
1196
|
+
# @return [TrueClass, FalseClass] depending on whether test succeeds.
|
1197
|
+
def test__binary_enc_dec args=ARGV
|
1198
|
+
stderr = @memory[:stderr]
|
1199
|
+
data, password = args
|
1200
|
+
stderr.print "[data]"
|
1201
|
+
data = binary_input_multi_line_non_echo [data]
|
1202
|
+
stderr.print "[password]"
|
1203
|
+
password = binary_input_single_line_non_echo [password]
|
1204
|
+
base64_encrypted, base64_iv, base64_salt, base64_iter, base64_key = binary_enc [password, data]
|
1205
|
+
dec_args = [password, base64_iv, base64_encrypted, nil, base64_salt, base64_iter]
|
1206
|
+
stderr.puts "# WARNING: secrets, including password are printed here. Storing them may be a major security incident."
|
1207
|
+
stderr.puts "# programmatically:"
|
1208
|
+
stderr.puts "binary_dec " + dec_args.to_s
|
1209
|
+
stderr.puts "# shell: "
|
1210
|
+
stderr.puts "#{$0} invoke_double p binary_dec " + (output_array_to_shell dec_args).to_s
|
1211
|
+
data_plain = binary_dec [password, base64_iv, base64_encrypted, nil, base64_salt, base64_iter]
|
1212
|
+
judgement =
|
1213
|
+
[
|
1214
|
+
[data, data_plain, "data"]
|
1215
|
+
].map(&method("expect_equal")).all?
|
1216
|
+
end
|
1217
|
+
|
1218
|
+
|
1219
|
+
# test for binary_enc and binary_dec_interactive.
|
1220
|
+
# good idea is to use this function once with the desired
|
1221
|
+
# data, password, and use the stderr output
|
1222
|
+
def test__binary_enc_dec_interactive args=ARGV
|
1223
|
+
stderr = @memory[:stderr]
|
1224
|
+
data, password, encrypted_base64_filename, data_is_base64 = args
|
1225
|
+
stderr.print "[data]"
|
1226
|
+
data = binary_input_multi_line_non_echo [data]
|
1227
|
+
stderr.print "[password]"
|
1228
|
+
password = binary_input_single_line_non_echo [password]
|
1229
|
+
stderr.puts
|
1230
|
+
base64_encrypted, base64_iv, base64_salt, base64_iter, base64_key = binary_enc [password, data, nil, nil, nil, data_is_base64 ]
|
1231
|
+
# the output is supposed to be safe to store,
|
1232
|
+
# so password is not placed in from binary_dec_interactive_args:
|
1233
|
+
dec_interactive_args = [base64_iv, base64_encrypted, base64_salt, base64_iter]
|
1234
|
+
stderr.puts "# programmatically:"
|
1235
|
+
stderr.puts "dec_interactive " + dec_interactive_args.to_s
|
1236
|
+
stderr.puts "# shell: "
|
1237
|
+
stderr.puts "#{$0} invoke_double puts binary_dec_interactive " + (output_array_to_shell dec_interactive_args).to_s
|
1238
|
+
stderr.puts "#or shell var:"
|
1239
|
+
stderr.puts "my_secret=$(#{$0} invoke_double puts binary_dec_interactive " + (output_array_to_shell dec_interactive_args).to_s + ")\necho $my_secret\nunset mysecret"
|
1240
|
+
encrypted_base64_filename && output_enc_file(dec_interactive_args + [encrypted_base64_filename])
|
1241
|
+
data_plain = binary_dec_interactive(dec_interactive_args + [password, data_is_base64])
|
1242
|
+
judgement =
|
1243
|
+
[
|
1244
|
+
[data.size, data_plain.size, "data.size"],
|
1245
|
+
[data, data_plain, "data"],
|
1246
|
+
].map(&method("expect_equal")).all?
|
1247
|
+
end
|
1248
|
+
|
1249
|
+
|
1250
|
+
# similar to
|
1251
|
+
# test__binary_enc_dec_interactive,
|
1252
|
+
# just that the data is ready from a file instead
|
1253
|
+
# note that there is an extra argument between
|
1254
|
+
# the args, the enc_out_filename.
|
1255
|
+
def test__binary_enc_dec_file_interactive args=ARGV
|
1256
|
+
stderr = @memory[:stderr]
|
1257
|
+
filename_or_url, enc_out_filename, password, data_is_base64 = args
|
1258
|
+
stderr.print "[filename_or_url]"
|
1259
|
+
filename_or_url = binary_input_multi_line_non_echo [filename_or_url]
|
1260
|
+
stderr.print "[output_filename_encrypted_data]"
|
1261
|
+
enc_out_filename = binary_input_multi_line_non_echo [enc_out_filename ]
|
1262
|
+
data = file_or_url_contents filename_or_url
|
1263
|
+
test__binary_enc_dec_interactive [ data, password, enc_out_filename, data_is_base64 ]
|
1264
|
+
end
|
1265
|
+
|
1266
|
+
|
1267
|
+
# basically the reverse of test__binary_enc_dec_file_interactive
|
1268
|
+
# planned improvements: still outputs to stdout
|
1269
|
+
def test__binary_dec_file_interactive args=ARGV
|
1270
|
+
stderr = @memory[:stderr]
|
1271
|
+
stdout = @memory[:stdout]
|
1272
|
+
enc_filename_or_url, out_filename, password, data_is_base64 = args
|
1273
|
+
stderr.print "[enc_filename_or_url]"
|
1274
|
+
enc_filename_or_url = binary_input_multi_line_non_echo [enc_filename_or_url]
|
1275
|
+
stderr.print "[output_filename_plain_data]"
|
1276
|
+
out_filename = binary_input_multi_line_non_echo [out_filename ]
|
1277
|
+
stderr.print "[password]"
|
1278
|
+
password = binary_input_single_line_non_echo [password]
|
1279
|
+
|
1280
|
+
output_dec_file [enc_filename_or_url, out_filename, password, data_is_base64]
|
1281
|
+
end
|
1282
|
+
|
1283
|
+
|
880
1284
|
# gem_spec
|
881
1285
|
# args (Array like the one returned by rubyment_gem_defaults)
|
882
1286
|
# returns: a gem spec string accordingly to args
|