nm_datafile 0.0.2 → 0.1.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 +4 -4
- data/README.md +41 -5
- data/changelog.md +9 -11
- data/lib/nm_datafile.rb +5 -16
- data/lib/nm_datafile/blowfish.rb +22 -0
- data/lib/nm_datafile/crypto.rb +12 -11
- data/lib/nm_datafile/data_loading.rb +13 -11
- data/lib/nm_datafile/debug.rb +5 -3
- data/lib/nm_datafile/file_encoding.rb +3 -20
- data/lib/nm_datafile/nm_datafile.rb +11 -6
- data/lib/nm_datafile/schema.rb +11 -11
- data/lib/nm_datafile/version.rb +1 -1
- data/spec/data/nmd_binary_string_w_2s_2li_2a_1ubws_1ep.zip +0 -0
- data/spec/nm_datafile_spec.rb +66 -8
- metadata +3 -3
- data/lib/nm_datafile/b_f.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9f642327532de8791b0c770ac2b7913cda8ebc20
|
4
|
+
data.tar.gz: 9d4cbcce8067f1dade4d236ef32c28ac95e1170b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 11f77b2b9617260f53c8aff8598ad150f825e3b9797ff68b2d1f077e0e9bd0f582a96b8793fb9ac11ca111828008de7b530a563096cc85e27dff85afa316a6c0
|
7
|
+
data.tar.gz: 8f6772c1df00df26f5daa60373012d894298eb2eba438071fed08bdd6b066565e25dddb4d850783cfb3be1d4ccaa5e0a4dc915d72bcbb5dac05ea3ae0a98a580
|
data/README.md
CHANGED
@@ -35,8 +35,7 @@ Or install it yourself as:
|
|
35
35
|
|
36
36
|
## Usage
|
37
37
|
|
38
|
-
First define a file Schema.
|
39
|
-
For instance, if you wanted a file type called 'shippable_file' and you wanted it to have many records of 'sales', 'line_items', etc,
|
38
|
+
First define a file Schema. For instance, if you wanted a file type called 'shippable_file' and you wanted it to have many records of 'sales', 'line_items', etc,
|
40
39
|
and you wanted your file to have a string of data named 'ready_for_shipment_batch', then you would define it like so.
|
41
40
|
|
42
41
|
$nm_datafile_schemas = {
|
@@ -48,11 +47,48 @@ and you wanted your file to have a string of data named 'ready_for_shipment_batc
|
|
48
47
|
}
|
49
48
|
}
|
50
49
|
|
51
|
-
|
50
|
+
First define a schema for your NmDatafile. For instance, if you wanted a file called 'data_file' and you just wanted a "strings" attribute where you can store an array of encrypted strings, then you could set the below schema.
|
52
51
|
|
53
|
-
|
52
|
+
NmDatafile::SCHEMA = {
|
53
|
+
schemas: {
|
54
|
+
:data_file => {
|
55
|
+
data_collections: [:strings], # name the data that is input into the NMDatafile as an array
|
56
|
+
data_objects: [:file_owners_name]
|
57
|
+
}
|
58
|
+
}
|
59
|
+
}
|
54
60
|
|
55
|
-
|
61
|
+
That's actually the default schema, so you don't need to set it, it's located in lib/nm_datafile/schema.rb, fyi :)
|
62
|
+
|
63
|
+
Now that you've got a schema set up, you can start using your data and easily serialize data into an encrypted file format.
|
64
|
+
|
65
|
+
nmd = NmDatafile.new(:data_file)
|
66
|
+
nmd.strings #=> []
|
67
|
+
nmd.strings << "hi"
|
68
|
+
nmd.file_owners_name = "dsj"
|
69
|
+
nmd.save_to_string # This is a binary string for programmers, you can write it to a file
|
70
|
+
nmd.save_to_file('/tmp/file.zip') # this saves your strings to a file
|
71
|
+
|
72
|
+
Ok, you've done all that, but your data is visible as that it's a zip file. So to turn sneaky mode on, you'll want to
|
73
|
+
|
74
|
+
NmDatafile.Load('/tmp/secret_file')
|
75
|
+
|
76
|
+
|
77
|
+
|
78
|
+
# Testing Note
|
79
|
+
|
80
|
+
Some cyphers are hardcoded in the tests... so if you make changes to the crypto algo, your tests will fail until you fix this...
|
81
|
+
|
82
|
+
|
83
|
+
# TODO
|
84
|
+
|
85
|
+
* Finish algo so it uses front door keys... encryption needs to be encrypted with the front door key
|
86
|
+
* Make it so the rails app sets up the schema file the proper way
|
87
|
+
* Specify encryption type in file schema? (symmetric vs asymmetric)
|
88
|
+
* Allow exporting data as a stenographic cat.jpg file.
|
89
|
+
* Better API for adding a new schema, and better default
|
90
|
+
* Bring in tests
|
91
|
+
* Allow PGP to be used to encrypt the file
|
56
92
|
|
57
93
|
|
58
94
|
## Contributing
|
data/changelog.md
CHANGED
@@ -1,19 +1,17 @@
|
|
1
1
|
### TODO:
|
2
2
|
|
3
3
|
* Fix the way there's an nm_datafile class... :(
|
4
|
-
* Define the
|
4
|
+
* Define the methods as static methods to make more clear where everything is
|
5
5
|
|
6
|
+
|
7
|
+
### 0.1.0
|
8
|
+
|
9
|
+
* Changed the syntax to accept a symmetric_key
|
10
|
+
* Fixed bug where fast_decrypt_string_with_pass doesn't implement any kind of password for encryption/ decryption...
|
11
|
+
* Fixed bug in the BF module by replacing it with better code
|
6
12
|
* Handle $FrontDoorKey
|
7
|
-
|
8
|
-
|
9
|
-
- it should also raise an exception if that instance variable isn't set
|
10
|
-
- Crypto::clean_decrypt_string is only used from within the gem!
|
11
|
-
- data_loading.rb
|
12
|
-
- nm_datafile.rb
|
13
|
-
|
14
|
-
- It's hard to tell what's an instance method and what's a class method
|
15
|
-
with all the mixin usage...
|
16
|
-
|
13
|
+
|
14
|
+
|
17
15
|
|
18
16
|
### 0.0.2
|
19
17
|
|
data/lib/nm_datafile.rb
CHANGED
@@ -2,35 +2,24 @@ require 'json'
|
|
2
2
|
require 'yaml'
|
3
3
|
require 'zip'
|
4
4
|
|
5
|
-
# require 'factory_girl'
|
6
|
-
# require 'pry'; binding.pry
|
7
|
-
# require File.expand_path('../../spec/factories/sales.rb', __FILE__)
|
8
|
-
|
9
5
|
require 'nm_datafile/version'
|
10
6
|
require 'nm_datafile/schema'
|
11
|
-
require 'nm_datafile/
|
7
|
+
require 'nm_datafile/blowfish'
|
12
8
|
require 'nm_datafile/data_loading'
|
13
9
|
require 'nm_datafile/crypto'
|
14
10
|
require 'nm_datafile/nm_datafile'
|
15
11
|
|
16
12
|
|
17
|
-
|
18
13
|
module NmDatafile
|
19
|
-
FRONT_DOOR_KEY = "$FrontDoorKey" # Write to NmDatafile::FRONT_DOOR_KEY to set a symetric key
|
20
|
-
@@symmetric_key = "$FrontDoorKey"
|
21
|
-
|
22
14
|
extend DataLoading
|
23
15
|
extend Crypto
|
16
|
+
extend FileEncoding
|
24
17
|
|
25
|
-
|
26
|
-
|
18
|
+
#config = {file_type: file_type, symmetric_key: symmetric_key}
|
19
|
+
def self.new(config, *args)
|
20
|
+
NmDatafile.new(config, *args)
|
27
21
|
end
|
28
22
|
|
29
|
-
def self.set_symmetric_key(val)
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
|
-
|
34
23
|
end
|
35
24
|
|
36
25
|
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# http://philtoland.com/post/807114394/simple-blowfish-encryption-with-ruby#notes
|
2
|
+
|
3
|
+
require "openssl"
|
4
|
+
|
5
|
+
module NmDatafile
|
6
|
+
|
7
|
+
module Blowfish
|
8
|
+
def self.cipher(mode, key, data)
|
9
|
+
cipher = OpenSSL::Cipher::Cipher.new('bf-cbc').send(mode)
|
10
|
+
cipher.key = Digest::SHA256.digest(key)
|
11
|
+
cipher.update(data) << cipher.final
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.encrypt(key, data)
|
15
|
+
cipher(:encrypt, key, data)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.decrypt(key, text)
|
19
|
+
cipher(:decrypt, key, text)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/nm_datafile/crypto.rb
CHANGED
@@ -22,10 +22,9 @@ module NmDatafile
|
|
22
22
|
|
23
23
|
# TODu: rename to decode_string_as_password_protected
|
24
24
|
def decode_string_as_password_protected(password, decryptable_portion)
|
25
|
-
|
26
|
-
bf = BF.new(password, true)
|
25
|
+
clear_text = Blowfish.decrypt(password, decryptable_portion)
|
27
26
|
|
28
|
-
|
27
|
+
clear_text
|
29
28
|
end
|
30
29
|
|
31
30
|
|
@@ -78,17 +77,17 @@ module NmDatafile
|
|
78
77
|
|
79
78
|
# This method needs to be available on the
|
80
79
|
# NmDatafile module
|
81
|
-
def clean_decrypt_string(string)
|
82
|
-
|
83
|
-
# decode_password_protected_string(@@unsecure_pass, string)
|
84
|
-
unsecure_pass = ::NmDatafile::FRONT_DOOR_KEY
|
85
|
-
fast_decrypt_string_with_pass(unsecure_pass, string)
|
80
|
+
def clean_decrypt_string(string, symmetric_key)
|
81
|
+
fast_decrypt_string_with_pass(symmetric_key, string)
|
86
82
|
end
|
87
83
|
|
88
|
-
|
84
|
+
def clean_encrypt_string(string, symmetric_key)
|
85
|
+
fast_encrypt_string_with_pass(symmetric_key, string)
|
86
|
+
end
|
89
87
|
|
90
88
|
def fast_encrypt_string_with_pass(pass, string)
|
91
|
-
|
89
|
+
passworded_string = encode_string_as_password_protected(string, pass)
|
90
|
+
encoded_as_base64 = Base64.encode64(passworded_string)
|
92
91
|
rearranged = rearrangement(encoded_as_base64)
|
93
92
|
obfs = obfuscated_ending(rearranged)
|
94
93
|
Base64.encode64(obfs)
|
@@ -98,9 +97,11 @@ module NmDatafile
|
|
98
97
|
obfs = Base64.decode64(string)
|
99
98
|
rearranged = obfuscated_ending_undo(obfs)
|
100
99
|
encoded_as_base64 = rearrangement_undo(rearranged)
|
101
|
-
Base64.decode64(encoded_as_base64)
|
100
|
+
passworded_string = Base64.decode64(encoded_as_base64)
|
101
|
+
clear_text_string = decode_password_protected_string(pass, passworded_string)
|
102
102
|
end
|
103
103
|
|
104
|
+
|
104
105
|
def rearrangement(s)
|
105
106
|
s = the_last_three_chars(s) + the_string_minus_the_last_three_chars(s)
|
106
107
|
end
|
@@ -4,17 +4,20 @@ module NmDatafile
|
|
4
4
|
|
5
5
|
# (m) Load: loads a file into memory as an NmDatafile
|
6
6
|
# TODO: Make lowercase
|
7
|
-
def Load(file_path)
|
7
|
+
def Load(file_path, symmetric_key)
|
8
8
|
zip_data = File.read(file_path)
|
9
|
-
|
9
|
+
load_binary_data(zip_data, symmetric_key)
|
10
10
|
end
|
11
11
|
|
12
12
|
# TODO: Make lowercase
|
13
|
-
def
|
14
|
-
hash = extract_entities_from_binary_data(binary_data)
|
13
|
+
def load_binary_data(binary_data, symmetric_key)
|
14
|
+
hash = extract_entities_from_binary_data(binary_data, symmetric_key)
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
config = { file_type: determine_file_type(hash[:attributes]),
|
17
|
+
symmetric_key: symmetric_key
|
18
|
+
}
|
19
|
+
|
20
|
+
nmd = NmDatafile.new( config )
|
18
21
|
|
19
22
|
nmd.load_attributes(hash[:attributes]) unless hash[:attributes].nil?
|
20
23
|
nmd.load_encryption(hash[:encryption])
|
@@ -28,15 +31,14 @@ module NmDatafile
|
|
28
31
|
end
|
29
32
|
|
30
33
|
|
31
|
-
def determine_password(hash)
|
34
|
+
def determine_password(hash, symmetric_key)
|
32
35
|
d = YAML::load hash[:encryption]
|
33
|
-
|
34
|
-
::NmDatafile.clean_decrypt_string(d["password"])
|
36
|
+
::NmDatafile.clean_decrypt_string(d["password"], symmetric_key)
|
35
37
|
end
|
36
38
|
|
37
39
|
# This method peers through a zip binary data blob and returns a hash consisting of
|
38
40
|
# { file_name1: file_data1, etc }
|
39
|
-
def extract_entities_from_binary_data(binary_data)
|
41
|
+
def extract_entities_from_binary_data(binary_data, symmetric_key)
|
40
42
|
binary_data_io = StringIO.new(binary_data)
|
41
43
|
|
42
44
|
hash = {}
|
@@ -46,7 +48,7 @@ module NmDatafile
|
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
49
|
-
password = self.determine_password(hash)
|
51
|
+
password = self.determine_password(hash, symmetric_key)
|
50
52
|
|
51
53
|
decrypt_encryptable_data!(password, hash)
|
52
54
|
hash
|
data/lib/nm_datafile/debug.rb
CHANGED
@@ -20,6 +20,8 @@ module NmDatafile
|
|
20
20
|
|
21
21
|
# creates an address_completion file based on the contents of the current shippable_file object
|
22
22
|
def simulate_address_completion_response(n_shipped)
|
23
|
+
symmetric_key = @symmetric_key
|
24
|
+
|
23
25
|
raise "can't make an address_completion_response unless it's a shippable_file" if @file_type != :shippable_file
|
24
26
|
setup_object_for_schema # TODu: I put this in, there was a bug in the test where it needs to be run... does it not run on init somehow?
|
25
27
|
|
@@ -32,10 +34,10 @@ module NmDatafile
|
|
32
34
|
erroneous_addresses << { "id" => sale["id"] }
|
33
35
|
end
|
34
36
|
end
|
35
|
-
|
37
|
+
|
36
38
|
simulated_response = [shipped_sales, erroneous_addresses, ready_for_shipment_batch]
|
37
|
-
|
38
|
-
nmd_address_completion = NmDatafile.new(
|
39
|
+
config = { file_type: :address_completion_file, symmetric_key: symmetric_key}
|
40
|
+
nmd_address_completion = NmDatafile.new(config, *simulated_response)
|
39
41
|
end
|
40
42
|
|
41
43
|
def generate_upload_params(action = "upload_shippable_file")
|
@@ -51,21 +51,15 @@ module NmDatafile
|
|
51
51
|
binary_output = `#{alt}`
|
52
52
|
end
|
53
53
|
|
54
|
+
# TODu: rename to encode_password_protected_string
|
54
55
|
def encode_string_as_password_protected(encryptable_portion, pass = nil)
|
55
|
-
#require 'b_f'
|
56
|
-
|
57
56
|
pish = @password
|
58
57
|
pish = pass unless pass.nil?
|
59
58
|
raise "error, password given was too long, must be 56 or less chars" if pish.length > 56
|
60
59
|
|
61
|
-
|
60
|
+
encrypted = Blowfish.encrypt(pish, encryptable_portion)
|
62
61
|
|
63
|
-
encrypted
|
64
|
-
end
|
65
|
-
|
66
|
-
|
67
|
-
def decode_password_protected_string(password, decryptable_portion)
|
68
|
-
::NmDatafile.decode_password_protected_string(password, decryptable_portion)
|
62
|
+
encrypted
|
69
63
|
end
|
70
64
|
|
71
65
|
def obfuscate_file_format
|
@@ -77,16 +71,5 @@ module NmDatafile
|
|
77
71
|
end
|
78
72
|
|
79
73
|
|
80
|
-
def clean_encrypt_string(string)
|
81
|
-
# Base64.encode64(encode_string_as_password_protected(string, @@unsecure_pass))
|
82
|
-
::NmDatafile.fast_encrypt_string_with_pass(::NmDatafile::FRONT_DOOR_KEY, string)
|
83
|
-
end
|
84
|
-
|
85
|
-
# This redirects to the mixin used by Crypto
|
86
|
-
# ughhh.....
|
87
|
-
def clean_decrypt_string(string)
|
88
|
-
::NmDatafile.clean_decrypt_string(string)
|
89
|
-
end
|
90
|
-
|
91
74
|
end
|
92
75
|
end
|
@@ -91,13 +91,15 @@ module NmDatafile
|
|
91
91
|
# (m)
|
92
92
|
# aNonyMousDatafile
|
93
93
|
class NmDatafile
|
94
|
-
@@schemas = ::NmDatafile::SCHEMA[:schemas] # TODO: move to initialize
|
95
94
|
@@clear_text_path = "clear_text_protected_nmd" # used for using system calls to decrypt and encrypt using a zip password
|
96
|
-
|
95
|
+
|
96
|
+
attr_reader :file_type, :password, :symmetric_key
|
97
|
+
attr_accessor :schemas
|
97
98
|
|
98
99
|
# include Crypto
|
99
100
|
include Debug
|
100
101
|
include FileEncoding
|
102
|
+
include Crypto
|
101
103
|
|
102
104
|
###############################
|
103
105
|
# Loading and Dumping Methods #
|
@@ -105,7 +107,10 @@ module NmDatafile
|
|
105
107
|
|
106
108
|
# notice migration to loading.rb
|
107
109
|
|
108
|
-
def initialize(
|
110
|
+
def initialize(config, *args)
|
111
|
+
file_type = config[:file_type]
|
112
|
+
@symmetric_key = config[:symmetric_key]
|
113
|
+
@schemas = ::NmDatafile::SCHEMA[:schemas]
|
109
114
|
set_file_type(file_type)
|
110
115
|
|
111
116
|
load_data(args)
|
@@ -122,7 +127,7 @@ module NmDatafile
|
|
122
127
|
def load_encryption(encryption_data)
|
123
128
|
d = YAML::load encryption_data
|
124
129
|
@integrity_hash = d["integrity_hash"] unless d["integrity_hash"].nil?
|
125
|
-
@password = clean_decrypt_string(d["password"]) unless d["password"].nil?
|
130
|
+
@password = ::NmDatafile.clean_decrypt_string(d["password"], @symmetric_key) unless d["password"].nil?
|
126
131
|
end
|
127
132
|
|
128
133
|
# (m) load_data: loads array of data into memory as an NmDatafile object
|
@@ -199,7 +204,7 @@ module NmDatafile
|
|
199
204
|
|
200
205
|
def build_encryption
|
201
206
|
hash = { integrity_hash: integrity_hash,
|
202
|
-
password: clean_encrypt_string(@password)
|
207
|
+
password: clean_encrypt_string(@password, @symmetric_key)
|
203
208
|
}.to_json
|
204
209
|
end
|
205
210
|
|
@@ -216,7 +221,7 @@ module NmDatafile
|
|
216
221
|
#######################
|
217
222
|
|
218
223
|
def schema
|
219
|
-
|
224
|
+
@schemas[@file_type]
|
220
225
|
end
|
221
226
|
|
222
227
|
def data_collection_names
|
data/lib/nm_datafile/schema.rb
CHANGED
@@ -2,15 +2,15 @@
|
|
2
2
|
# something more generic
|
3
3
|
module NmDatafile
|
4
4
|
SCHEMA = { schemas:
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
5
|
+
{ :shippable_file => {
|
6
|
+
data_collections: [:sales, :line_items, :discounts, :addresses, :ubws, :encryption_pairs], # name the data that is input into the NMDatafile as an array
|
7
|
+
data_objects: [:ready_for_shipment_batch]
|
8
|
+
},
|
9
|
+
|
10
|
+
:address_completion_file => {
|
11
|
+
data_collections: [:sales, :erroneous_sales],
|
12
|
+
data_objects: [:ready_for_shipment_batch]
|
13
|
+
}
|
14
|
+
}
|
15
|
+
}
|
16
16
|
end
|
data/lib/nm_datafile/version.rb
CHANGED
Binary file
|
data/spec/nm_datafile_spec.rb
CHANGED
@@ -6,13 +6,36 @@ describe "nm_datafile" do
|
|
6
6
|
#@sample_data = get_sample_data
|
7
7
|
@sales = [{"address_id"=>1, "created_at"=>"2015-03-08T03:54:51Z", "currency_used"=>"BTC"}]
|
8
8
|
@sample_data = [ @sales ]
|
9
|
-
|
9
|
+
# binary_nmd_info:
|
10
|
+
# decrypted password should be: "@(OfMLpCe@pV(GGLuEvj(Tup$BaFodP3!6^5%5pTW"
|
11
|
+
#
|
12
|
+
# if you change the encryption algo, recreate this file with the help of the first test
|
13
|
+
@binary_nmd_path = 'spec/data/nmd_binary_string_w_2s_2li_2a_1ubws_1ep.zip'
|
14
|
+
|
15
|
+
@symmetric_key = "this_is_a_keythis_is_a_keythis_is_a_keythis_is_a_key"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should be able to create an nmd_file out of complicated data hashes and save it" do
|
19
|
+
sales = [{"address_id"=>1, "created_at"=>"2015-03-23T01:55:04Z", "currency_used"=>"BTC", "delivery_acknowledged"=>nil, "id"=>1, "original_id"=>nil, "prepped"=>true, "ready_for_shipment_batch_id"=>1, "receipt_confirmed"=>"2015-03-23T01:55:04Z", "sale_amount"=>"4500000.0", "shipped"=>nil, "shipping_amount"=>0.0, "total_amount"=>"4500000.0", "updated_at"=>"2015-03-23T01:55:04Z", "user_id"=>1, "utilized_bitcoin_wallet_id"=>1}, {"address_id"=>5, "created_at"=>"2015-03-23T01:55:04Z", "currency_used"=>"BTC", "delivery_acknowledged"=>nil, "id"=>2, "original_id"=>nil, "prepped"=>true, "ready_for_shipment_batch_id"=>1, "receipt_confirmed"=>"2015-03-23T01:55:04Z", "sale_amount"=>"4500000.0", "shipped"=>nil, "shipping_amount"=>0.0, "total_amount"=>"4500000.0", "updated_at"=>"2015-03-23T01:55:04Z", "user_id"=>2, "utilized_bitcoin_wallet_id"=>1}]
|
20
|
+
line_items = [{"created_at"=>"2015-03-23T01:55:04Z", "currency_used"=>"BTC", "description"=>nil, "discount"=>nil, "discounted_amount"=>nil, "discounted_item_id"=>nil, "id"=>1, "original_id"=>nil, "price"=>"4500000.0", "price_after_product_discounts"=>nil, "price_extend"=>"4500000.0", "product_sku"=>"0001", "qty"=>1, "sale_id"=>1, "shipping_cost"=>"0.0", "shipping_cost_btc"=>0, "shipping_cost_usd"=>"0.0", "updated_at"=>"2015-03-23T01:55:04Z"}, {"created_at"=>"2015-03-23T01:55:04Z", "currency_used"=>"BTC", "description"=>nil, "discount"=>nil, "discounted_amount"=>nil, "discounted_item_id"=>nil, "id"=>2, "original_id"=>nil, "price"=>"4500000.0", "price_after_product_discounts"=>nil, "price_extend"=>"4500000.0", "product_sku"=>"0001", "qty"=>1, "sale_id"=>2, "shipping_cost"=>"0.0", "shipping_cost_btc"=>0, "shipping_cost_usd"=>"0.0", "updated_at"=>"2015-03-23T01:55:04Z"}]
|
21
|
+
discounts = []
|
22
|
+
addresses = [{"address1"=>"-----BEGIN PGP MESSAGE-----\nVersion: haneWIN JavascriptPG v2.0\n\nhQEMAxi+vIcfDgArAQgAkkLLYWOzmHDrknH9NWLjTz7cmMN6Da7Oqz57WFQS\n3vdFb/72BrdpHnzZRmZNIWBH4Vj7sUcKv0X2Q+WL45qQSELEdOawpgGVvS9A\nXrqzAJxbTBKTpyqszqfD/Q8pTMnCIXo0S1zJERBpqLvxQF2rO+sytMn6x9xZ\n2ZFKWtpSfcYxR89itnCK3tCBNHH9hJG+ej/oFsXwJgddVuSnRRSPPW6Ea/W2\n9G4xuOVnDwpfOLGj7wfP6+AlMuJCGTN6Urd18eGyFiYP+WaPvk51yS4jkzOi\nkqRbRLTIvsEiK2KcVyEd6F/NxqTLD7Nw5ADxHyVZzOiNPJKTmwf7diaP8mdm\nyqQzC8c5mfPzWhop3DYJXzL2Y4Mgk7qxR08RKIewTR/SWLtlRnFOwT+itBQN\nN4nD1x19T0Wp\n=dsyQ\n-----END PGP MESSAGE-----\n", "address2"=>"-----BEGIN PGP MESSAGE-----\nVersion: haneWIN JavascriptPG v2.0\n\nhQEMAxi+vIcfDgArAQf6AloPtxXYB+OGv+MnFgQofqs6CEMbKoSf45c+hk6c\nZMpqr9/R/ZK6I7Nbla/FCbKmAtttZ0T6I1GAS/6ivFDJ8J7Y7bhag2tueP86\ntMfyTL6j6VQGOEu7AoMrx58vk76bC2DYG8BAw42y6lHifz8X9IJAzrccyjT4\nHzYmUmoM2sma3qHuN1PZp24qZJqHEOGr8XhpTzaDXuIp00P3+X0NVoLzaZUS\ncgxObRImRzHyRSzSHKRnnbTKHg7SKn43J2lpkJV07bqP8HLNTGYG1YzUigjp\nPydGX0l1sLjo4I3KTmBetjs5s4sJTH3QqqYq/Dfqfch5/MqE92LrNlxzCtgc\ncKQwpTllOo0smnSBLrTnixgEy0mfhUlmVjasEoG9DxD0yinJR+9TeCeskPQk\nKdXI8L/O\n=Mx2r\n-----END PGP MESSAGE-----\n", "apt"=>"-----BEGIN PGP MESSAGE-----\nVersion: haneWIN JavascriptPG v2.0\n\nhQEMAxi+vIcfDgArAQf/QWtqnGOuYOQqhdv9rot0N8altMdgso71Deub2YqH\nyVSrrLhzpvT6mPmNJXHOuS0AtamnNjeMbiJRmkf3m6l56BMYlz904GIbG3Zr\nzzJcr8A+N30afhMO/kmZZfK5mjLfKHiyPA71HN5Kd3J8N9aWYwj9HDm3tCSB\ndsOvcZ5QXkXwzIj+jtOV1201PvwMyShmTgZqCM7c0OwR/sFKBOhx33tcZKWx\nW+k0jbfZJb0RUv95jPuQIeS180O5BRWSUC2tOXaCkgT9u6pC41sRjTZnuH+3\nv/DIhV7uyf46f00sCcwpxPedtrchydh+Daww7sPpdQpRKWtk19a+iIIo8Rvt\n7KQkA0Y5WuvhTQbdfq8deJzUwqUKJtGVGPcps1PMeIMe6ZTLi0ru\n=Gmsg\n-----END PGP MESSAGE-----", "city"=>"-----BEGIN PGP MESSAGE-----\nVersion: haneWIN JavascriptPG v2.0\n\nhQEMAxi+vIcfDgArAQgAqPKhl8LbI8Fs+zasPS3a61CWCS8Aus7UgR8Bf3Eu\n4UBPOA7B3U4YQXhMoxMYGl/JN0C6IctjkP6PwyKXvNTgpKG1WKuki8/hKKZg\njPLhiDwZeFggzCTqC0GxublCrQOPZjHNUufShCY5D1g/iTKTO3VCuilUDyBj\nt3ExgO8k/SgdfbzzrKNe3TktJTOFMOenwr0QQg51B3XrBLih5/ssHWVnrs06\nmBlC6jucHY/tuPIAiQj7xJBpncUHJZbqbvkm0xsb8QFFzSoNyCV+3rekpil5\nYlbb9i3Vtr7BIwEowHvqjKaubEy58bxk7F+P5XrLj+yabV9vzUH1xeqFkEwY\n3KQq1wOGUHMqR9hmZZfkT70jIo3/+7Wxd8g+RZnH6Sh0jQ6E8i4wTtVgjoCV\n\n=ZHnk\n-----END PGP MESSAGE-----\n", "code_name"=>"My House 5", "country"=>"-----BEGIN PGP MESSAGE-----\nVersion: haneWIN JavascriptPG v2.0\n\nhQEMAxi+vIcfDgArAQgArZZDnWPNSpRwVLfzAuhcOXN0CpX8X70ZeN7pUkUS\nQomf5LpvQ+31dVgCdOpkcf/NgL5fnr7CaJLQ7ovC3f9tz+oxirfRT/SueGL5\nhDqQIPE23y0UPoLeNBh8krzhz72o9fQAa3fHG50KCgJpizyUHXaOxo8i8+eA\nkzcGTaL12jeTrDSxoy8xGj/xZyS/m1HbcJ7ZdVSChZt72xe/Cj4epgC1SD4b\nvm7Ki90EOcY8NylRBeR8/yFKsY3YSE+kF7snD94N2M2O9or+wgT61iXZMYf0\ntKeK1woU4C+SnBIo+H+Aa6X4s3OGiFH0GyTxfr+C0r4FzSTO1LcioIq5m6GS\nWqQiVhyzg6XScDqB3Je7CGEEjA6oFzOmQmn3Rsa2ZnYNHaqP6g==\n=RvKD\n-----END PGP MESSAGE-----\n", "created_at"=>"2015-03-23T01:55:04Z", "encryption_pair_id"=>1, "erroneous"=>false, "first_name"=>"-----BEGIN PGP MESSAGE-----\nVersion: haneWIN JavascriptPG v2.0\n\nhQEMAxi+vIcfDgArAQf/UTM9RsZfkWBG3PzkHzm6GtCBmjXAwbHeSg00rKIe\nMdikzxnm464wG1sM0WDJeQCVQGzGIAkxfvOPU4rnfhq6x/NJpI7WuC4X1uJw\niyxiZnpT/A2PEYdlWbUZQWeeadEgAMdI+yiPJ/SHbQrmWDwLEhpKtwCqjMYi\nhtJt1W1l+lhAMdGvXh6nIVyQWiqm9+pQrEvewWIAKsxcFk2OGKSfMRRtivWl\nECNCI8z8h0WdIythAVHTJ8CzmEszYuMWRG7LUMhUs3IHNAtCWkoRojISY1/4\nKqSqQlhpMwJmYGebPhGiAarpmjtltZA/Dy7ERFfctoLxjE7BkRK7HXnq13XW\n4qQk0lyBxx/TadYmlCzDu/B6riOUsbCHJQiwQPpv9+D/CPdK9NWI\n=Awa8\n-----END PGP MESSAGE-----\n", "id"=>1, "last_name"=>"-----BEGIN PGP MESSAGE-----\nVersion: haneWIN JavascriptPG v2.0\n\nhQEMAxi+vIcfDgArAQf+O6lcxOYNW9a4E46TUfcYm4dSoUeEMXKjdk9RmWvj\no49h2EOWbjR+LoyAYFah9GF8ydBwkrI47dyeokZDJq9lnHQrZdO3BEPzEfd3\nxZ7bPAH7kVennN4kkon/uh5cnwQdFcIQufkUWPePIOTM37GVEMwiUWSAk6Tv\nsd/hC11UraLgJV/iQ1PKYrQ1k9JFab4qYMNg3vdJCS2i5EmVUldlhxhw2odq\nU0e03FM0zjA6oe7/zoci7tYRsvMbDIr7gnNk75s4xKHmA73879uiEgCUXisd\nEJtAiCoAi357VJvIGM9p/rLAzBiL3Q8K3LWKWVzjvPp5tIIQZMAF50FF/f9u\nA6Qjh6R1leS5aGd6NwEzd6udN4hM+ORUDMUrKNgjGcFhzwFnTrE=\n=bbtQ\n-----END PGP MESSAGE-----\n", "original_id"=>nil, "phone"=>nil, "state"=>"-----BEGIN PGP MESSAGE-----\nVersion: haneWIN JavascriptPG v2.0\n\nhQEMAxi+vIcfDgArAQgAwSy1/X1hRxDkEgX0WTe8EWKCyacxW2J4jvv5/kDM\nZBpOLi78KCCVokrp2hmdkTzM0aJQl45/dkImVOYOpXb9ulnCJXbmpyF6398d\nvbGTvjtLXQSaJ41LbCGxu32L1bCQsrBUIORqqL/+C9gdqrMmYItWDXwN2do5\nWfVhJShOJEWULSUrhYOC40BuRLKNrv2ruk48bh7Mdn7DQbaBa0jT4iV6flK7\nmFvZfAULPOM40UBJ9aCF/GQGBR7lPM3SiaUHfi3rWQihjpUEmHE1l/ui7FWw\n+FiaKvKWhvECAIo5iV9V/sUPGj3Zw5JEDFX9J4GS6zry2G9/sU1Ka7nOQx3F\nOqQnazqWUIMO9WCMZRV/6gnw7rbOr897ikGXvOdoMY4scVb8dz8bbLT9\n=s04T\n-----END PGP MESSAGE-----\n", "updated_at"=>"2015-03-23T01:55:04Z", "user_id"=>1, "zip"=>"-----BEGIN PGP MESSAGE-----\nVersion: haneWIN JavascriptPG v2.0\n\nhQEMAxi+vIcfDgArAQgAqyLtfr8yy9aRSNCKy9UTNVhVFFs1ABozP2QUUKVJ\nfA/oUeAntTmeFz1Ga7HC1g8iyefE1G/Y2PEaHCSj1JFqczOJS13XgRYO45AK\nd9dTLLjl+qElVx78M06mIoXUaeSuaex0X/3qNXauCIeGJpaBf9xMLMlYbxH8\nzW3Q1j15VnQz6MFuwoYNXfABc2ekLve076UvUCxbn0G598VmCHHCD28u+Oec\nsuuxebOcjQWbFNsLoGTpKS+OecilkQ98H1cPkLD7qZHluGWP+0WCOCkg1Ttq\nvW+ibdmGW30fq/1EKprJchayANgGdMd/ynbduG0Nn0pGYUk+y5WBucMDINGS\nZKQlHHtkqVBbH14dmx81aGg2gblp6PVaa/fmFw/2FP385ARJ1mRT3w==\n=PlFx\n-----END PGP MESSAGE-----\n"}, {"address1"=>"-----BEGIN PGP MESSAGE-----\nVersion: haneWIN JavascriptPG v2.0\n\nhQEMAxi+vIcfDgArAQgAkkLLYWOzmHDrknH9NWLjTz7cmMN6Da7Oqz57WFQS\n3vdFb/72BrdpHnzZRmZNIWBH4Vj7sUcKv0X2Q+WL45qQSELEdOawpgGVvS9A\nXrqzAJxbTBKTpyqszqfD/Q8pTMnCIXo0S1zJERBpqLvxQF2rO+sytMn6x9xZ\n2ZFKWtpSfcYxR89itnCK3tCBNHH9hJG+ej/oFsXwJgddVuSnRRSPPW6Ea/W2\n9G4xuOVnDwpfOLGj7wfP6+AlMuJCGTN6Urd18eGyFiYP+WaPvk51yS4jkzOi\nkqRbRLTIvsEiK2KcVyEd6F/NxqTLD7Nw5ADxHyVZzOiNPJKTmwf7diaP8mdm\nyqQzC8c5mfPzWhop3DYJXzL2Y4Mgk7qxR08RKIewTR/SWLtlRnFOwT+itBQN\nN4nD1x19T0Wp\n=dsyQ\n-----END PGP MESSAGE-----\n", "address2"=>"-----BEGIN PGP MESSAGE-----\nVersion: haneWIN JavascriptPG v2.0\n\nhQEMAxi+vIcfDgArAQf6AloPtxXYB+OGv+MnFgQofqs6CEMbKoSf45c+hk6c\nZMpqr9/R/ZK6I7Nbla/FCbKmAtttZ0T6I1GAS/6ivFDJ8J7Y7bhag2tueP86\ntMfyTL6j6VQGOEu7AoMrx58vk76bC2DYG8BAw42y6lHifz8X9IJAzrccyjT4\nHzYmUmoM2sma3qHuN1PZp24qZJqHEOGr8XhpTzaDXuIp00P3+X0NVoLzaZUS\ncgxObRImRzHyRSzSHKRnnbTKHg7SKn43J2lpkJV07bqP8HLNTGYG1YzUigjp\nPydGX0l1sLjo4I3KTmBetjs5s4sJTH3QqqYq/Dfqfch5/MqE92LrNlxzCtgc\ncKQwpTllOo0smnSBLrTnixgEy0mfhUlmVjasEoG9DxD0yinJR+9TeCeskPQk\nKdXI8L/O\n=Mx2r\n-----END PGP MESSAGE-----\n", "apt"=>"", "city"=>"-----BEGIN PGP MESSAGE-----\nVersion: haneWIN JavascriptPG v2.0\n\nhQEMAxi+vIcfDgArAQgAqPKhl8LbI8Fs+zasPS3a61CWCS8Aus7UgR8Bf3Eu\n4UBPOA7B3U4YQXhMoxMYGl/JN0C6IctjkP6PwyKXvNTgpKG1WKuki8/hKKZg\njPLhiDwZeFggzCTqC0GxublCrQOPZjHNUufShCY5D1g/iTKTO3VCuilUDyBj\nt3ExgO8k/SgdfbzzrKNe3TktJTOFMOenwr0QQg51B3XrBLih5/ssHWVnrs06\nmBlC6jucHY/tuPIAiQj7xJBpncUHJZbqbvkm0xsb8QFFzSoNyCV+3rekpil5\nYlbb9i3Vtr7BIwEowHvqjKaubEy58bxk7F+P5XrLj+yabV9vzUH1xeqFkEwY\n3KQq1wOGUHMqR9hmZZfkT70jIo3/+7Wxd8g+RZnH6Sh0jQ6E8i4wTtVgjoCV\n\n=ZHnk\n-----END PGP MESSAGE-----\n", "code_name"=>"My House 9", "country"=>"-----BEGIN PGP MESSAGE-----\nVersion: haneWIN JavascriptPG v2.0\n\nhQEMAxi+vIcfDgArAQgArZZDnWPNSpRwVLfzAuhcOXN0CpX8X70ZeN7pUkUS\nQomf5LpvQ+31dVgCdOpkcf/NgL5fnr7CaJLQ7ovC3f9tz+oxirfRT/SueGL5\nhDqQIPE23y0UPoLeNBh8krzhz72o9fQAa3fHG50KCgJpizyUHXaOxo8i8+eA\nkzcGTaL12jeTrDSxoy8xGj/xZyS/m1HbcJ7ZdVSChZt72xe/Cj4epgC1SD4b\nvm7Ki90EOcY8NylRBeR8/yFKsY3YSE+kF7snD94N2M2O9or+wgT61iXZMYf0\ntKeK1woU4C+SnBIo+H+Aa6X4s3OGiFH0GyTxfr+C0r4FzSTO1LcioIq5m6GS\nWqQiVhyzg6XScDqB3Je7CGEEjA6oFzOmQmn3Rsa2ZnYNHaqP6g==\n=RvKD\n-----END PGP MESSAGE-----\n", "created_at"=>"2015-03-23T01:55:04Z", "encryption_pair_id"=>1, "erroneous"=>false, "first_name"=>"-----BEGIN PGP MESSAGE-----\nVersion: haneWIN JavascriptPG v2.0\n\nhQEMAxi+vIcfDgArAQf/UTM9RsZfkWBG3PzkHzm6GtCBmjXAwbHeSg00rKIe\nMdikzxnm464wG1sM0WDJeQCVQGzGIAkxfvOPU4rnfhq6x/NJpI7WuC4X1uJw\niyxiZnpT/A2PEYdlWbUZQWeeadEgAMdI+yiPJ/SHbQrmWDwLEhpKtwCqjMYi\nhtJt1W1l+lhAMdGvXh6nIVyQWiqm9+pQrEvewWIAKsxcFk2OGKSfMRRtivWl\nECNCI8z8h0WdIythAVHTJ8CzmEszYuMWRG7LUMhUs3IHNAtCWkoRojISY1/4\nKqSqQlhpMwJmYGebPhGiAarpmjtltZA/Dy7ERFfctoLxjE7BkRK7HXnq13XW\n4qQk0lyBxx/TadYmlCzDu/B6riOUsbCHJQiwQPpv9+D/CPdK9NWI\n=Awa8\n-----END PGP MESSAGE-----\n", "id"=>5, "last_name"=>"-----BEGIN PGP MESSAGE-----\nVersion: haneWIN JavascriptPG v2.0\n\nhQEMAxi+vIcfDgArAQf+O6lcxOYNW9a4E46TUfcYm4dSoUeEMXKjdk9RmWvj\no49h2EOWbjR+LoyAYFah9GF8ydBwkrI47dyeokZDJq9lnHQrZdO3BEPzEfd3\nxZ7bPAH7kVennN4kkon/uh5cnwQdFcIQufkUWPePIOTM37GVEMwiUWSAk6Tv\nsd/hC11UraLgJV/iQ1PKYrQ1k9JFab4qYMNg3vdJCS2i5EmVUldlhxhw2odq\nU0e03FM0zjA6oe7/zoci7tYRsvMbDIr7gnNk75s4xKHmA73879uiEgCUXisd\nEJtAiCoAi357VJvIGM9p/rLAzBiL3Q8K3LWKWVzjvPp5tIIQZMAF50FF/f9u\nA6Qjh6R1leS5aGd6NwEzd6udN4hM+ORUDMUrKNgjGcFhzwFnTrE=\n=bbtQ\n-----END PGP MESSAGE-----\n", "original_id"=>nil, "phone"=>nil, "state"=>"-----BEGIN PGP MESSAGE-----\nVersion: haneWIN JavascriptPG v2.0\n\nhQEMAxi+vIcfDgArAQgAwSy1/X1hRxDkEgX0WTe8EWKCyacxW2J4jvv5/kDM\nZBpOLi78KCCVokrp2hmdkTzM0aJQl45/dkImVOYOpXb9ulnCJXbmpyF6398d\nvbGTvjtLXQSaJ41LbCGxu32L1bCQsrBUIORqqL/+C9gdqrMmYItWDXwN2do5\nWfVhJShOJEWULSUrhYOC40BuRLKNrv2ruk48bh7Mdn7DQbaBa0jT4iV6flK7\nmFvZfAULPOM40UBJ9aCF/GQGBR7lPM3SiaUHfi3rWQihjpUEmHE1l/ui7FWw\n+FiaKvKWhvECAIo5iV9V/sUPGj3Zw5JEDFX9J4GS6zry2G9/sU1Ka7nOQx3F\nOqQnazqWUIMO9WCMZRV/6gnw7rbOr897ikGXvOdoMY4scVb8dz8bbLT9\n=s04T\n-----END PGP MESSAGE-----\n", "updated_at"=>"2015-03-23T01:55:04Z", "user_id"=>2, "zip"=>"-----BEGIN PGP MESSAGE-----\nVersion: haneWIN JavascriptPG v2.0\n\nhQEMAxi+vIcfDgArAQgAqyLtfr8yy9aRSNCKy9UTNVhVFFs1ABozP2QUUKVJ\nfA/oUeAntTmeFz1Ga7HC1g8iyefE1G/Y2PEaHCSj1JFqczOJS13XgRYO45AK\nd9dTLLjl+qElVx78M06mIoXUaeSuaex0X/3qNXauCIeGJpaBf9xMLMlYbxH8\nzW3Q1j15VnQz6MFuwoYNXfABc2ekLve076UvUCxbn0G598VmCHHCD28u+Oec\nsuuxebOcjQWbFNsLoGTpKS+OecilkQ98H1cPkLD7qZHluGWP+0WCOCkg1Ttq\nvW+ibdmGW30fq/1EKprJchayANgGdMd/ynbduG0Nn0pGYUk+y5WBucMDINGS\nZKQlHHtkqVBbH14dmx81aGg2gblp6PVaa/fmFw/2FP385ARJ1mRT3w==\n=PlFx\n-----END PGP MESSAGE-----\n"}]
|
23
|
+
ubws = [{"created_at"=>"2015-03-23T01:55:04Z", "id"=>1, "original_id"=>nil, "updated_at"=>"2015-03-23T01:55:04Z", "wallet_address"=>"1FWNSL4HZy7pW2zRHanR2t72nvw7VdLVuB"}]
|
24
|
+
encryption_pairs = [{"created_at"=>"2015-03-23T01:55:04Z", "id"=>1, "original_id"=>nil, "private_key"=>nil, "public_key"=>"-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: GnuPG v1.4.12 (GNU/Linux)\n\nmQENBFLm15sBCADGEjoJw/ATyPYC+3er/XiZsCCht6t1Kr8p6fXVI9h7cyvoTulM\n31iug8kFvIr/dggNtEVYjnzuk6ervf2mit5uw3wgs8BBDGOj7BLg6kfuEUjsRaRO\nlCNKKneuscCBvyDbilsnc9jOdc7Nz4wpa8nwLh9iM6GqcM90pClaGYsDAYSFL7Kz\nHiTkBeDeo6pQS2p7G7p+Fg498OrpvythBtwhNiVL01X8f2zaGhlkTaDThJm5qofG\nlal552FitRtJuwu6Tim2Fef2jqJoEb0Hxc4o59/kKm+hqYlW0p5qleKm/hNWDSp1\nFA4VlUP7IPqPa5mzrIIrpRhDRZaIkdGAqWchABEBAAG0EWFiY2RlIChhKSA8YUBi\nLmM+iQE4BBMBAgAiBQJS5tebAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAK\nCRAdhYud6iaPu+yoB/4lyX2WTLFQWKCYavU4OzSiRSwSg33LAa/hj9as4jDUErg0\nIPl2dm3QMpf57jny1stqEDAVBQ3eyff5LqmJnhf6YyfroyfCMuTbY4woNyaY2IC0\nXJlBdMlUAOoWcHZCfl4ud97vW+XfRky/uZsmjUBh5DymL2f0fVFxwIeXl/k0hOti\n0FY6l7EGl0I9MQp5dPdqJonsAv1KnjdclsqmLDu7cFWHNF+BHCTb3xkDs0kqShvs\nA8o8HrD/9kUxdRSVdO+VQrZaimI6XdNWHzI4pEYQHQtnZ0IA1aOyzcqWpyTSlyy8\n1QzyNAvXQ4gzrpqRwdrdqUjuEwUTJoLKRSyYQ8yCuQENBFLm15sBCADI6MESgCQH\nf2JIjsHk2owRMpEhjyr25pEktjTpf8zLy5LYwHgwZXwpc6zDnwMBV6PcaPI6ZTRF\nGfwY4GsL9DBLefbiZuvYghYi++cevG11V87XhoRx8u8FGPukjRyKs4gCTrHW2g9q\n8IES46GZalCkC4x8WDM68yWutO/22ie7eALjMU+Ju9lbrwUI4/uy6a9dQJLMPdXN\ncYnWQO/q/CpkcngnoKEjreJ9FszrdSFtd+cBoItknsX668Euf4IIPwCW/KUfGZMm\n/Js/3pZRQpqq+OryuKcB03YsMd5E/JE+DySUo19rPeA2xwXLlW5goA9JL0YCvqW/\ntmEwvwDoVlW5ABEBAAGJAR8EGAECAAkFAlLm15sCGwwACgkQHYWLneomj7tfowgA\ngKRy023Oa6rYKwEZlQRWc7gL27Z8V9vCFgBaMM4cNFqrKqY97VezZ6ldjYqd6AGJ\nGWbrG8SqVZ4ZyoksyWnweMYKqoRGIcX7LEuL97mc6W7bB5MRGL9zQRIxu0/KHVik\nVZ8PL3f4j4XdPuF0gRLPBIDOOZVGqf86NpnKLx1XEIaS/z3OqxyWkRR47oOquqpd\nNd4Gn1hDZlTgiSsaSf6aFdS6O2eDLaseZ2l0WgrWoUMjD5bzmKgpmaJAJ+CcfuvB\nP1O44KOH9l+pRzKCbr6nlfd8rbQ4kehjIaGchdehvLFv9WQWMH9uDkKgIu3BGGkp\nJ1TdTyeCX++qX0MtJ79GDw==\n=ToNu\n-----END PGP PUBLIC KEY BLOCK-----\n", "test_value"=>nil, "tested"=>nil, "updated_at"=>"2015-03-23T01:55:04Z"}]
|
25
|
+
rfsb = {"acf_integrity_hash"=>nil, "batch_stamp"=>"2015-03-23_01.55.042", "created_at"=>"2015-03-23T01:55:04Z", "id"=>1, "original_id"=>nil, "sale_id"=>nil, "sf_integrity_hash"=>"c39c2be15b918842604261d8daf9ef1535842a7d558d0b6f2114a9404dd453d8", "updated_at"=>"2015-03-23T01:55:04Z"}
|
26
|
+
|
27
|
+
config = {file_type: :shippable_file, symmetric_key: @symmetric_key}
|
28
|
+
nm_data = NmDatafile.new(config, sales, line_items, discounts, addresses, ubws, encryption_pairs, rfsb)
|
29
|
+
nm_data.sales.count.should eq 2
|
30
|
+
|
31
|
+
# uncomment to update file
|
32
|
+
#nm_data.save_to_file(@binary_nmd_path)
|
10
33
|
end
|
11
34
|
|
12
35
|
it "should be able to load data from a binary string" do
|
13
36
|
nmd_binary_string = File.read(@binary_nmd_path)
|
14
37
|
|
15
|
-
nmd_file = NmDatafile::
|
38
|
+
nmd_file = NmDatafile::load_binary_data nmd_binary_string, @symmetric_key
|
16
39
|
|
17
40
|
sales = nmd_file.sales
|
18
41
|
line_items = nmd_file.line_items
|
@@ -22,7 +45,8 @@ describe "nm_datafile" do
|
|
22
45
|
encryption_pairs = nmd_file.encryption_pairs
|
23
46
|
rfsb = nmd_file.ready_for_shipment_batch
|
24
47
|
|
25
|
-
|
48
|
+
config = {file_type: :shippable_file, symmetric_key: @symmetric_key}
|
49
|
+
nm_data = NmDatafile.new(config, sales, line_items, discounts, addresses, ubws, encryption_pairs, rfsb)
|
26
50
|
|
27
51
|
nm_data.sales.count.should eq 2
|
28
52
|
nm_data.ready_for_shipment_batch["batch_stamp"].should eq rfsb["batch_stamp"]
|
@@ -30,26 +54,60 @@ describe "nm_datafile" do
|
|
30
54
|
|
31
55
|
it "should be able to load data from a path to a zip" do
|
32
56
|
|
33
|
-
nmd_string_loaded = NmDatafile::
|
57
|
+
nmd_string_loaded = NmDatafile::load_binary_data File.read(@binary_nmd_path), @symmetric_key
|
34
58
|
|
35
|
-
nmd_path_loaded = NmDatafile::Load @binary_nmd_path
|
59
|
+
nmd_path_loaded = NmDatafile::Load @binary_nmd_path, @symmetric_key
|
36
60
|
|
37
61
|
nmd_string_loaded.sales.should eq nmd_path_loaded.sales
|
38
62
|
end
|
39
63
|
|
40
64
|
it "should be able to save data as a zip string" do
|
41
|
-
|
65
|
+
config = {file_type: :shippable_file, symmetric_key: @symmetric_key}
|
66
|
+
nmd_shippable = NmDatafile.new(config, *@sample_data)
|
42
67
|
|
43
|
-
nmd = NmDatafile::
|
68
|
+
nmd = NmDatafile::load_binary_data nmd_shippable.save_to_string, @symmetric_key
|
44
69
|
|
45
70
|
nmd.sales.should eq @sample_data.first
|
46
71
|
end
|
47
72
|
|
48
73
|
it "should be able to load in the attributes" do
|
49
|
-
nmd = NmDatafile::Load @binary_nmd_path
|
74
|
+
nmd = NmDatafile::Load @binary_nmd_path, @symmetric_key
|
50
75
|
|
51
76
|
nmd.file_type.should eq :shippable_file
|
52
77
|
end
|
78
|
+
|
79
|
+
it "fast_encrypt_string_with_pass and fast_decrypt_string_with_pass reverse" do
|
80
|
+
original_string = "hello"
|
81
|
+
|
82
|
+
pass = @symmetric_key
|
83
|
+
|
84
|
+
encrypted_string = NmDatafile::fast_encrypt_string_with_pass(pass, original_string)
|
85
|
+
|
86
|
+
clear_text = NmDatafile::fast_decrypt_string_with_pass(pass, encrypted_string)
|
87
|
+
|
88
|
+
clear_text.should eq original_string
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should test simulate_address_completion_response(n_shipped)" do
|
92
|
+
nmd_file = NmDatafile::Load @binary_nmd_path, @symmetric_key
|
93
|
+
|
94
|
+
x = nmd_file.simulate_address_completion_response(5)
|
95
|
+
|
96
|
+
x.sales.count.should eq 2
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should test generate_upload_params" do
|
100
|
+
nmd_file = NmDatafile::Load @binary_nmd_path, @symmetric_key
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should fail when the wrong symmetric key is used" do
|
104
|
+
encrypted = ::NmDatafile.clean_encrypt_string("encrypt this string please", "this_is_a_keythi")
|
105
|
+
|
106
|
+
expect {
|
107
|
+
clear_text = ::NmDatafile.clean_decrypt_string(encrypted, "this_is_a_keythasdf")
|
108
|
+
}.to raise_error
|
109
|
+
end
|
110
|
+
|
53
111
|
|
54
112
|
|
55
113
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nm_datafile
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- dsj
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-06-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubyzip
|
@@ -97,7 +97,7 @@ files:
|
|
97
97
|
- Rakefile
|
98
98
|
- changelog.md
|
99
99
|
- lib/nm_datafile.rb
|
100
|
-
- lib/nm_datafile/
|
100
|
+
- lib/nm_datafile/blowfish.rb
|
101
101
|
- lib/nm_datafile/crypto.rb
|
102
102
|
- lib/nm_datafile/data_loading.rb
|
103
103
|
- lib/nm_datafile/debug.rb
|
data/lib/nm_datafile/b_f.rb
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
# https://gist.github.com/nono/2995118
|
2
|
-
|
3
|
-
require "openssl"
|
4
|
-
|
5
|
-
module NmDatafile
|
6
|
-
|
7
|
-
class BF < Struct.new(:key, :pad_with_spaces)
|
8
|
-
def encrypt(str)
|
9
|
-
cipher = OpenSSL::Cipher.new('bf-ecb').encrypt
|
10
|
-
if pad_with_spaces
|
11
|
-
str += " " until str.bytesize % 8 == 0
|
12
|
-
cipher.padding = 0
|
13
|
-
end
|
14
|
-
cipher.key = key
|
15
|
-
binary_data = cipher.update(str) << cipher.final
|
16
|
-
hex_encoded = binary_data.unpack('H*').first
|
17
|
-
end
|
18
|
-
|
19
|
-
def decrypt(hex_encoded)
|
20
|
-
cipher = OpenSSL::Cipher.new('bf-ecb').decrypt
|
21
|
-
cipher.padding = 0 if pad_with_spaces
|
22
|
-
cipher.key = key
|
23
|
-
binary_data = [hex_encoded].pack('H*')
|
24
|
-
str = cipher.update(binary_data) << cipher.final
|
25
|
-
str.force_encoding(Encoding::UTF_8)
|
26
|
-
str
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
|
33
|
-
|