adyen_jpiqueras 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.travis.yml +30 -0
- data/CHANGELOG.md +128 -0
- data/CONTRIBUTING.md +85 -0
- data/Gemfile +11 -0
- data/LICENSE +21 -0
- data/README.md +31 -0
- data/Rakefile +54 -0
- data/adyen_jpiqueras.gemspec +44 -0
- data/config.ru +5 -0
- data/lib/adyen.rb +16 -0
- data/lib/adyen/api.rb +424 -0
- data/lib/adyen/api/cacert.pem +3894 -0
- data/lib/adyen/api/payment_service.rb +374 -0
- data/lib/adyen/api/recurring_service.rb +188 -0
- data/lib/adyen/api/response.rb +61 -0
- data/lib/adyen/api/simple_soap_client.rb +134 -0
- data/lib/adyen/api/templates/payment_service.rb +159 -0
- data/lib/adyen/api/templates/recurring_service.rb +71 -0
- data/lib/adyen/api/test_helpers.rb +133 -0
- data/lib/adyen/api/xml_querier.rb +137 -0
- data/lib/adyen/base.rb +17 -0
- data/lib/adyen/configuration.rb +179 -0
- data/lib/adyen/form.rb +419 -0
- data/lib/adyen/hpp.rb +27 -0
- data/lib/adyen/hpp/request.rb +192 -0
- data/lib/adyen/hpp/response.rb +52 -0
- data/lib/adyen/hpp/signature.rb +34 -0
- data/lib/adyen/matchers.rb +92 -0
- data/lib/adyen/notification_generator.rb +30 -0
- data/lib/adyen/railtie.rb +13 -0
- data/lib/adyen/rest.rb +67 -0
- data/lib/adyen/rest/authorise_payment.rb +234 -0
- data/lib/adyen/rest/authorise_recurring_payment.rb +46 -0
- data/lib/adyen/rest/client.rb +127 -0
- data/lib/adyen/rest/errors.rb +33 -0
- data/lib/adyen/rest/modify_payment.rb +89 -0
- data/lib/adyen/rest/payout.rb +89 -0
- data/lib/adyen/rest/request.rb +104 -0
- data/lib/adyen/rest/response.rb +80 -0
- data/lib/adyen/rest/signature.rb +27 -0
- data/lib/adyen/signature.rb +76 -0
- data/lib/adyen/templates/notification_migration.rb +29 -0
- data/lib/adyen/templates/notification_model.rb +69 -0
- data/lib/adyen/util.rb +147 -0
- data/lib/adyen/version.rb +5 -0
- data/spec/api/api_spec.rb +231 -0
- data/spec/api/payment_service_spec.rb +505 -0
- data/spec/api/recurring_service_spec.rb +236 -0
- data/spec/api/response_spec.rb +59 -0
- data/spec/api/simple_soap_client_spec.rb +133 -0
- data/spec/api/spec_helper.rb +463 -0
- data/spec/api/test_helpers_spec.rb +84 -0
- data/spec/functional/api_spec.rb +117 -0
- data/spec/functional/initializer.rb.ci +3 -0
- data/spec/functional/initializer.rb.sample +3 -0
- data/spec/spec_helper.rb +8 -0
- data/test/form_test.rb +303 -0
- data/test/functional/payment_authorisation_api_test.rb +107 -0
- data/test/functional/payment_modification_api_test.rb +58 -0
- data/test/functional/payout_api_test.rb +93 -0
- data/test/helpers/capybara.rb +12 -0
- data/test/helpers/configure_adyen.rb +6 -0
- data/test/helpers/example_server.rb +136 -0
- data/test/helpers/public/adyen.encrypt.js +679 -0
- data/test/helpers/public/adyen.encrypt.min.js +14 -0
- data/test/helpers/test_cards.rb +20 -0
- data/test/helpers/views/authorized.erb +7 -0
- data/test/helpers/views/hpp.erb +20 -0
- data/test/helpers/views/index.erb +6 -0
- data/test/helpers/views/pay.erb +36 -0
- data/test/helpers/views/redirect_shopper.erb +18 -0
- data/test/hpp/signature_test.rb +37 -0
- data/test/hpp_test.rb +250 -0
- data/test/integration/hpp_integration_test.rb +52 -0
- data/test/integration/payment_using_3d_secure_integration_test.rb +41 -0
- data/test/integration/payment_with_client_side_encryption_integration_test.rb +26 -0
- data/test/rest/signature_test.rb +36 -0
- data/test/rest_list_recurring_details_response_test.rb +22 -0
- data/test/rest_request_test.rb +43 -0
- data/test/rest_response_test.rb +19 -0
- data/test/signature_test.rb +76 -0
- data/test/test_helper.rb +45 -0
- data/test/util_test.rb +78 -0
- data/yard_extensions.rb +16 -0
- metadata +308 -0
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'adyen/rest'
|
3
|
+
|
4
|
+
class PaymentAuthorisationAPITest < Minitest::Test
|
5
|
+
def setup
|
6
|
+
@client = Adyen::REST.client
|
7
|
+
end
|
8
|
+
|
9
|
+
def teardown
|
10
|
+
@client.close
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_payment_api_request
|
14
|
+
response = @client.authorise_payment(
|
15
|
+
merchantAccount: 'VanBergenORG',
|
16
|
+
amount: { currency: 'EUR', value: 1234 },
|
17
|
+
reference: 'Test order #1',
|
18
|
+
card: Adyen::TestCards::VISA
|
19
|
+
)
|
20
|
+
|
21
|
+
assert response.authorised?
|
22
|
+
assert response.psp_reference
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_refused_payment_api_request
|
26
|
+
response = @client.authorise_payment(
|
27
|
+
merchantAccount: 'VanBergenORG',
|
28
|
+
amount: { currency: 'EUR', value: 1234 },
|
29
|
+
reference: 'Test order #1',
|
30
|
+
card: Adyen::TestCards::VISA.merge(cvc: '123')
|
31
|
+
)
|
32
|
+
|
33
|
+
assert response.refused?
|
34
|
+
assert response.psp_reference
|
35
|
+
assert response.has_attribute?(:refusal_reason)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_payment_with_3d_secure_api_request
|
39
|
+
response = @client.authorise_payment(
|
40
|
+
merchantAccount: 'VanBergenORG',
|
41
|
+
amount: { currency: 'EUR', value: 1234 },
|
42
|
+
reference: 'Test order #1',
|
43
|
+
card: Adyen::TestCards::MASTERCARD_3DSECURE,
|
44
|
+
browser_info: {
|
45
|
+
acceptHeader: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
46
|
+
userAgent: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008052912 Firefox/3.0"
|
47
|
+
}
|
48
|
+
)
|
49
|
+
|
50
|
+
assert response.redirect_shopper?
|
51
|
+
assert response.psp_reference
|
52
|
+
assert response.has_attribute?(:md)
|
53
|
+
assert_equal "https://test.adyen.com/hpp/3d/validate.shtml", response['issuer_url']
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_initial_recurring_payment_api_request
|
57
|
+
response = @client.authorise_recurring_payment(
|
58
|
+
merchantAccount: 'VanBergenORG',
|
59
|
+
shopper_email: 'willem@van-bergen.org',
|
60
|
+
shopper_reference: 'willem42',
|
61
|
+
amount: { currency: 'EUR', value: 1234 },
|
62
|
+
reference: 'Test initial recurring payment order #1',
|
63
|
+
card: Adyen::TestCards::VISA
|
64
|
+
)
|
65
|
+
|
66
|
+
assert response.authorised?
|
67
|
+
assert response.psp_reference
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_recurring_payment_api_request
|
71
|
+
response = @client.reauthorise_recurring_payment(
|
72
|
+
merchantAccount: 'VanBergenORG',
|
73
|
+
shopper_email: 'willem@van-bergen.org',
|
74
|
+
shopper_reference: 'willem42',
|
75
|
+
amount: { currency: 'EUR', value: 1234 },
|
76
|
+
reference: 'Test recurring payment order #1'
|
77
|
+
)
|
78
|
+
|
79
|
+
assert response.authorised?
|
80
|
+
assert response.psp_reference
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_list_recurring_details_api_request
|
84
|
+
response = @client.list_recurring_details(
|
85
|
+
merchantAccount: 'VanBergenORG',
|
86
|
+
recurring: { contract: "RECURRING" },
|
87
|
+
shopper_reference: 'willem42',
|
88
|
+
)
|
89
|
+
|
90
|
+
assert !response.details.first[:recurring_detail_reference].empty?
|
91
|
+
assert_equal response.details.first[:card_holder_name], Adyen::TestCards::VISA[:holder_name]
|
92
|
+
assert_equal response.details.first[:card_expiry_month].to_i, Adyen::TestCards::VISA[:expiry_month].to_i
|
93
|
+
assert_equal response.details.first[:card_expiry_year], Adyen::TestCards::VISA[:expiry_year]
|
94
|
+
assert_equal response.details.first[:card_number], Adyen::TestCards::VISA[:number][-4..-1]
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
def test_list_recurring_references_api_request
|
99
|
+
response = @client.list_recurring_details(
|
100
|
+
merchantAccount: 'VanBergenORG',
|
101
|
+
recurring: { contract: "RECURRING" },
|
102
|
+
shopper_reference: 'willem42',
|
103
|
+
)
|
104
|
+
|
105
|
+
assert_equal response.references.first, response.details.first[:recurring_detail_reference]
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'adyen/rest'
|
3
|
+
|
4
|
+
class PaymentModificationAPITest < Minitest::Test
|
5
|
+
def setup
|
6
|
+
@client = Adyen::REST.client
|
7
|
+
end
|
8
|
+
|
9
|
+
def teardown
|
10
|
+
@client.close
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_capture_payment_api_request
|
14
|
+
response = @client.capture_payment(
|
15
|
+
merchantAccount: 'VanBergenORG',
|
16
|
+
modification_amount: { currency: 'EUR', value: 1234 },
|
17
|
+
reference: "functional test for cancellation",
|
18
|
+
original_reference: 7913939284323855
|
19
|
+
)
|
20
|
+
|
21
|
+
assert response.received?
|
22
|
+
assert response.psp_reference
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_cancel_payment_api_request
|
26
|
+
response = @client.cancel_payment(
|
27
|
+
merchantAccount: 'VanBergenORG',
|
28
|
+
reference: "functional test for cancellation",
|
29
|
+
original_reference: 7913939284323855
|
30
|
+
)
|
31
|
+
|
32
|
+
assert response.received?
|
33
|
+
assert response.psp_reference
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_refund_payment_api_request
|
37
|
+
response = @client.refund_payment(
|
38
|
+
merchantAccount: 'VanBergenORG',
|
39
|
+
modification_amount: { currency: 'EUR', value: 1234 },
|
40
|
+
reference: "functional test for cancellation",
|
41
|
+
original_reference: 7913939284323855
|
42
|
+
)
|
43
|
+
|
44
|
+
assert response.received?
|
45
|
+
assert response.psp_reference
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_cancel_or_refund_payment_api_request
|
49
|
+
response = @client.cancel_or_refund_payment(
|
50
|
+
merchantAccount: 'VanBergenORG',
|
51
|
+
reference: "functional test for cancellation",
|
52
|
+
original_reference: 7913939284323855
|
53
|
+
)
|
54
|
+
|
55
|
+
assert response.received?
|
56
|
+
assert response.psp_reference
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'adyen/rest'
|
3
|
+
|
4
|
+
class PayoutAPITest < Minitest::Test
|
5
|
+
def setup
|
6
|
+
@client = Adyen::REST::Client.new(
|
7
|
+
:test,
|
8
|
+
'storePayout@Company.VanBergen',
|
9
|
+
'xxWWcc'
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
def teardown
|
14
|
+
@client.close
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_submit_and_store_request
|
18
|
+
response = @client.submit_and_store_payout(
|
19
|
+
merchantAccount: 'VanBergenORG',
|
20
|
+
amount: { currency: 'EUR', value: 20},
|
21
|
+
bank: { iban: 'NL48RABO0132394782', bankName: 'Rabobank', countryCode: 'NL', ownerName: 'Test shopper' },
|
22
|
+
recurring: { contract: 'PAYOUT' },
|
23
|
+
reference: 'PayoutPayment-0001',
|
24
|
+
shopperEmail: 'shopper@example.com',
|
25
|
+
shopperReference: 'ShopperFoo'
|
26
|
+
)
|
27
|
+
|
28
|
+
assert response.received?
|
29
|
+
assert response.psp_reference
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_store_request
|
33
|
+
response = @client.store_payout(
|
34
|
+
merchantAccount: 'VanBergenORG',
|
35
|
+
bank: { iban: 'NL48RABO0132394782', bankName: 'Rabobank', countryCode: 'NL', ownerName: 'Test shopper' },
|
36
|
+
recurring: { contract: 'PAYOUT' },
|
37
|
+
shopperEmail: 'shopper@example.com',
|
38
|
+
shopperReference: 'ShopperFoo'
|
39
|
+
)
|
40
|
+
|
41
|
+
assert response.success?
|
42
|
+
assert response.psp_reference
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_submit_request
|
46
|
+
response = @client.submit_payout(
|
47
|
+
merchantAccount: 'VanBergenORG',
|
48
|
+
amount: { currency: 'EUR', value: 20 },
|
49
|
+
recurring: { contract: 'PAYOUT' },
|
50
|
+
reference: 'PayoutPayment-0001',
|
51
|
+
shopperEmail: 'shopper@example.com',
|
52
|
+
shopperReference: 'ShopperFoo',
|
53
|
+
selectedRecurringDetailReference: 'LATEST'
|
54
|
+
)
|
55
|
+
|
56
|
+
assert response.received?
|
57
|
+
assert response.psp_reference
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class PayoutReviewTest < Minitest::Test
|
62
|
+
def setup
|
63
|
+
@client = Adyen::REST::Client.new(
|
64
|
+
:test,
|
65
|
+
'reviewPayout@Company.VanBergen',
|
66
|
+
'ssWWcc'
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
def teardown
|
71
|
+
@client.close
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_confirm_payout
|
75
|
+
response = @client.confirm_payout(
|
76
|
+
merchantAccount: 'VanBergenORG',
|
77
|
+
originalReference: '1234'
|
78
|
+
)
|
79
|
+
|
80
|
+
assert response.confirmed?
|
81
|
+
assert response.psp_reference
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_decline_payout
|
85
|
+
response = @client.decline_payout(
|
86
|
+
merchantAccount: 'VanBergenORG',
|
87
|
+
originalReference: '1234'
|
88
|
+
)
|
89
|
+
|
90
|
+
assert response.declined?
|
91
|
+
assert response.psp_reference
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'helpers/example_server'
|
2
|
+
require 'capybara/dsl'
|
3
|
+
require 'capybara/poltergeist'
|
4
|
+
|
5
|
+
Capybara.register_driver :poltergeist do |app|
|
6
|
+
Capybara::Poltergeist::Driver.new(app, phantomjs_options: ['--ssl-protocol=any'])
|
7
|
+
end
|
8
|
+
|
9
|
+
Capybara.default_driver = :poltergeist
|
10
|
+
Capybara.javascript_driver = :poltergeist
|
11
|
+
Capybara.app = Adyen::ExampleServer
|
12
|
+
|
@@ -0,0 +1,6 @@
|
|
1
|
+
Adyen.configuration.default_api_params = { :merchant_account => 'VanBergenORG' }
|
2
|
+
Adyen.configuration.api_username = 'ws@Company.VanBergen'
|
3
|
+
Adyen.configuration.api_password = '7phtHzbfnzsp'
|
4
|
+
Adyen.configuration.cse_public_key = '10001|AC2CEF7D1BE904AF35B76467927A7044CCFC470E725B4D5327CC143BC5245983A56A4E5B0AC969F7F706F4B4A81B184DE2ECEA229CDBB943E6F7D6AD1623604F66640D1F2FAE1E4AE80EE1E5D4486AA8F553F6CE47BF57C8EFEF745E731AE27DD7B74F8895D41DA8339CC32677E4BD35288EC2FB9A18D46E7E3DFF5C7DD6D756F2223BED29427E5899A5877F0E9D1FAA50C17F8C96BA96DFA79BD04B1116366FFEE33F1BD18B8C3694BACBF8BFC7E2045CB9FFFEFA49AAB18EF1D9E9710A16B7DC67433ABD3A4FD3661CD9F5B1967753E4DC744DD3A1F8C8BED87827EED443CBED06A0D5C86C329406BE452B9A6EB997EE43A9FA7241A74E87AC3FC898F327CD'
|
5
|
+
Adyen.configuration.register_form_skin(:testing, 'tifSfXeX', 'testing123', :merchant_account => 'VanBergenORG')
|
6
|
+
Adyen.configuration.default_skin = :testing
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'adyen'
|
2
|
+
require 'sinatra'
|
3
|
+
|
4
|
+
require 'helpers/configure_adyen'
|
5
|
+
|
6
|
+
class Adyen::ExampleServer < Sinatra::Base
|
7
|
+
set :views, File.join(File.dirname(__FILE__), 'views')
|
8
|
+
set :public_folder, File.join(File.dirname(__FILE__), 'public')
|
9
|
+
|
10
|
+
get '/' do
|
11
|
+
erb :index
|
12
|
+
end
|
13
|
+
|
14
|
+
get '/hpp' do
|
15
|
+
@payment = {
|
16
|
+
:currency_code => 'EUR',
|
17
|
+
:payment_amount => 4321,
|
18
|
+
:merchant_reference => params[:merchant_reference] || 'HPP test order',
|
19
|
+
:ship_before_date => (Date.today + 1).strftime('%F'),
|
20
|
+
:session_validity => (Time.now.utc + 30*60).strftime('%FT%TZ'),
|
21
|
+
:billing_address => {
|
22
|
+
:street => 'Alexanderplatz',
|
23
|
+
:house_number_or_name => '0815',
|
24
|
+
:city => 'Berlin',
|
25
|
+
:postal_code => '10119',
|
26
|
+
:state_or_province => 'Berlin',
|
27
|
+
:country => 'Germany',
|
28
|
+
},
|
29
|
+
:shopper => {
|
30
|
+
:telephone_number => '123-4512-345',
|
31
|
+
:first_name => 'John',
|
32
|
+
:last_name => 'Doe',
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
erb :hpp
|
37
|
+
end
|
38
|
+
|
39
|
+
get '/form' do
|
40
|
+
@payment = {
|
41
|
+
:skin => :testing,
|
42
|
+
:currency_code => 'EUR',
|
43
|
+
:payment_amount => 4321,
|
44
|
+
:merchant_reference => params[:merchant_reference] || 'HPP test order',
|
45
|
+
:ship_before_date => (Date.today + 1).strftime('%F'),
|
46
|
+
:session_validity => (Time.now.utc + 30*60).strftime('%FT%TZ'),
|
47
|
+
:billing_address => {
|
48
|
+
:street => 'Alexanderplatz',
|
49
|
+
:house_number_or_name => '0815',
|
50
|
+
:city => 'Berlin',
|
51
|
+
:postal_code => '10119',
|
52
|
+
:state_or_province => 'Berlin',
|
53
|
+
:country => 'Germany',
|
54
|
+
},
|
55
|
+
:shopper => {
|
56
|
+
:telephone_number => '123-4512-345',
|
57
|
+
:first_name => 'John',
|
58
|
+
:last_name => 'Doe',
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
erb :hpp
|
63
|
+
end
|
64
|
+
|
65
|
+
get '/hpp/result' do
|
66
|
+
raise "Forgery!" unless Adyen::HPP::Response(params).has_valid_signature?
|
67
|
+
|
68
|
+
case params['authResult']
|
69
|
+
when 'AUTHORISED'
|
70
|
+
@attributes = {
|
71
|
+
psp_reference: params['pspReference'],
|
72
|
+
merchant_reference: params['merchantReference'],
|
73
|
+
}
|
74
|
+
erb :authorized
|
75
|
+
else
|
76
|
+
status 400
|
77
|
+
body params['authResult']
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
get '/pay' do
|
82
|
+
erb :pay
|
83
|
+
end
|
84
|
+
|
85
|
+
post '/pay' do
|
86
|
+
api_request = Adyen::REST.client.authorise_payment_request
|
87
|
+
api_request[:merchant_account] = 'VanBergenORG'
|
88
|
+
api_request[:reference] = 'Test order #1'
|
89
|
+
api_request.set_amount('EUR', 1234)
|
90
|
+
api_request.set_encrypted_card_data(request)
|
91
|
+
api_request.set_browser_info(request)
|
92
|
+
|
93
|
+
api_response = Adyen::REST.client.execute_request(api_request)
|
94
|
+
@attributes = {
|
95
|
+
psp_reference: api_response.psp_reference
|
96
|
+
}
|
97
|
+
|
98
|
+
if api_response.redirect_shopper?
|
99
|
+
@term_url = request.url.sub(%r{/pay\z}, '/pay/3dsecure')
|
100
|
+
@issuer_url = api_response[:issuer_url]
|
101
|
+
@md = api_response[:md]
|
102
|
+
@pa_request = api_response[:pa_request]
|
103
|
+
|
104
|
+
erb :redirect_shopper
|
105
|
+
|
106
|
+
elsif api_response.authorised?
|
107
|
+
erb :authorized
|
108
|
+
|
109
|
+
else
|
110
|
+
status 400
|
111
|
+
body api_response[:refusal_reason]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
post '/pay/3dsecure' do
|
116
|
+
api_request = Adyen::REST.client.authorise_payment_3dsecure_request
|
117
|
+
api_request[:merchant_account] = 'VanBergenORG'
|
118
|
+
api_request.set_browser_info(request)
|
119
|
+
api_request.set_3d_secure_parameters(request)
|
120
|
+
|
121
|
+
api_response = Adyen::REST.client.execute_request(api_request)
|
122
|
+
|
123
|
+
@attributes = {
|
124
|
+
psp_reference: api_response.psp_reference,
|
125
|
+
auth_code: api_response[:auth_code],
|
126
|
+
}
|
127
|
+
|
128
|
+
if api_response.authorised?
|
129
|
+
erb :authorized
|
130
|
+
|
131
|
+
else
|
132
|
+
status 400
|
133
|
+
body api_response[:refusal_reason]
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,679 @@
|
|
1
|
+
/*
|
2
|
+
*
|
3
|
+
* Client Encryption of Forms.
|
4
|
+
*
|
5
|
+
* Includes:
|
6
|
+
* * RSA and ECC in JavaScript | http://www-cs-students.stanford.edu/~tjw/jsbn/
|
7
|
+
* * Stanford Javascript Crypto Library | http://crypto.stanford.edu/sjcl/
|
8
|
+
* * JSON in JavaScript | http://www.JSON.org/
|
9
|
+
*
|
10
|
+
* Version: 0_1_7
|
11
|
+
* Author: ADYEN (c) 2014
|
12
|
+
|
13
|
+
<!DOCTYPE html>
|
14
|
+
<html lang="en">
|
15
|
+
<head>
|
16
|
+
<title>Example Payment Form</title>
|
17
|
+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
<form method="POST" action="#handler" id="adyen-encrypted-form">
|
21
|
+
<fieldset>
|
22
|
+
<legend>Card Details</legend>
|
23
|
+
<div class="field">
|
24
|
+
<label for="adyen-encrypted-form-number">Card Number
|
25
|
+
<input type="text" id="adyen-encrypted-form-number" value="5555444433331111" size="20" autocomplete="off" data-encrypted-name="number" />
|
26
|
+
</label>
|
27
|
+
</div>
|
28
|
+
|
29
|
+
<div class="field">
|
30
|
+
<label for="adyen-encrypted-form-holder-name">Card Holder Name
|
31
|
+
<input type="text" id="adyen-encrypted-form-holder-name" value="John Doe" size="20" autocomplete="off" data-encrypted-name="holderName" />
|
32
|
+
</label>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<div class="field">
|
36
|
+
<label for="adyen-encrypted-form-cvc">CVC
|
37
|
+
<input type="text" id="adyen-encrypted-form-cvc" value="737" size="4" maxlength="4" autocomplete="off" data-encrypted-name="cvc" />
|
38
|
+
</label>
|
39
|
+
</div>
|
40
|
+
|
41
|
+
<div class="field">
|
42
|
+
<label for="adyen-encrypted-form-expiry-month">Expiration Month (MM)
|
43
|
+
<input type="text" value="06" id="adyen-encrypted-form-expiry-month" maxlength="2" size="2" autocomplete="off" data-encrypted-name="expiryMonth" /> /
|
44
|
+
</label>
|
45
|
+
<label for="adyen-encrypted-form-expiry-year">Expiration Year (YYYY)
|
46
|
+
<input type="text" value="2016" id="adyen-encrypted-form-expiry-year" maxlength="4" size="4" autocomplete="off" data-encrypted-name="expiryYear" />
|
47
|
+
</label>
|
48
|
+
</div>
|
49
|
+
|
50
|
+
<div class="field">
|
51
|
+
<input type="hidden" id="adyen-encrypted-form-expiry-generationtime" value="generate-this-server-side" data-encrypted-name="generationtime" />
|
52
|
+
<input type="submit" value="Submit" />
|
53
|
+
</div>
|
54
|
+
</fieldset>
|
55
|
+
</form>
|
56
|
+
|
57
|
+
<!-- How to use the Adyen encryption client-side JS library -->
|
58
|
+
<!-- N.B. Make sure the library is *NOT* loaded in the "head" of the HTML document -->
|
59
|
+
<script src="js/adyen.encrypt.min.js?0_1_7"></script>
|
60
|
+
<script>
|
61
|
+
// generate time client side for testing only... Don't deploy on a real integration!!!
|
62
|
+
document.getElementById('adyen-encrypted-form-expiry-generationtime').value = new Date().toISOString();
|
63
|
+
|
64
|
+
// the form element to encrypt
|
65
|
+
var form = document.getElementById('adyen-encrypted-form');
|
66
|
+
|
67
|
+
// the public key
|
68
|
+
var key = "10001|80C7821C961865FB4AD23F172E220F819A5CC7B9956BC3458E2788"
|
69
|
+
+ "F9D725B07536E297B89243081916AAF29E26B7624453FC84CB10FC7DF386"
|
70
|
+
+ "31B3FA0C2C01765D884B0DA90145FCE217335BCDCE4771E30E6E5630E797"
|
71
|
+
+ "EE289D3A712F93C676994D2746CBCD0BEDD6D29618AF45FA6230C1D41FE1"
|
72
|
+
+ "DB0193B8FA6613F1BD145EA339DAC449603096A40DC4BF8FACD84A5D2CA5"
|
73
|
+
+ "ECFC59B90B928F31715A7034E7B674E221F1EB1D696CC8B734DF7DE2E309"
|
74
|
+
+ "E6E8CF94156686558522629E8AF59620CBDE58327E9D84F29965E4CD0FAF"
|
75
|
+
+ "A38C632B244287EA1F7F70DAA445D81C216D3286B09205F6650262CAB415"
|
76
|
+
+ "5F024B3294A933F4DC514DE0B5686F6C2A6A2D";
|
77
|
+
|
78
|
+
var options = {};
|
79
|
+
|
80
|
+
// Enable basic field validation (default is true)
|
81
|
+
// The submit button will be disabled when fields
|
82
|
+
// proof to be invalid. The form submission will be
|
83
|
+
// prevented as well.
|
84
|
+
// options.enableValidations = true,
|
85
|
+
|
86
|
+
// Always have the submit button enabled (default is false)
|
87
|
+
// Leave the submit button enabled, even in case
|
88
|
+
// of validation errors.
|
89
|
+
// options.submitButtonAlwaysEnabled = false,
|
90
|
+
|
91
|
+
// Ignore non-numeric characters in the card number field (default is true)
|
92
|
+
// The payment handling ignores non-numeric characters for the card field.
|
93
|
+
// By default non-numeric characters will also be ignored while validating
|
94
|
+
// the card number field. This can be disabled for UX reasons.
|
95
|
+
// options.numberIgnoreNonNumeric = true,
|
96
|
+
|
97
|
+
// the form will be encrypted before it is submitted
|
98
|
+
adyen.encrypt.createEncryptedForm( form, key, options);
|
99
|
+
|
100
|
+
</script>
|
101
|
+
</body>
|
102
|
+
</html>
|
103
|
+
|
104
|
+
*
|
105
|
+
*/
|
106
|
+
|
107
|
+
(function() {
|
108
|
+
|
109
|
+
/* typedarray.js */
|
110
|
+
(function(){try{var b=[new Uint8Array(1),new Uint32Array(1),new Int32Array(1)];return}catch(g){}function f(e,a){return this.slice(e,a)}function c(j,e){if(arguments.length<2){e=0}for(var a=0,h=j.length;a<h;++a,++e){this[e]=j[a]&255}}function d(e){var a;if(typeof e==="number"){a=new Array(e);for(var h=0;h<e;++h){a[h]=0}}else{a=e.slice(0)}a.subarray=f;a.buffer=a;a.byteLength=a.length;a.set=c;if(typeof e==="object"&&e.buffer){a.buffer=e.buffer}return a}try{window.Uint8Array=d}catch(g){}try{window.Uint32Array=d}catch(g){}try{window.Int32Array=d}catch(g){}})();(function(){if("response" in XMLHttpRequest.prototype||"mozResponseArrayBuffer" in XMLHttpRequest.prototype||"mozResponse" in XMLHttpRequest.prototype||"responseArrayBuffer" in XMLHttpRequest.prototype){return}try{Object.defineProperty(XMLHttpRequest.prototype,"response",{get:function(){return new Uint8Array(new VBArray(this.responseBody).toArray())}})}catch(a){}})();(function(){if("btoa" in window){return}var a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";window.btoa=function(g){var e="";var f,d;for(f=0,d=g.length;f<d;f+=3){var k=g.charCodeAt(f)&255;var j=g.charCodeAt(f+1)&255;var h=g.charCodeAt(f+2)&255;var c=k>>2,b=((k&3)<<4)|(j>>4);var m=f+1<d?((j&15)<<2)|(h>>6):64;var l=f+2<d?(h&63):64;e+=a.charAt(c)+a.charAt(b)+a.charAt(m)+a.charAt(l)}return e}})();/* */
|
111
|
+
|
112
|
+
/* json2.js */
|
113
|
+
if(typeof JSON!=="object"){JSON={}}(function(){function f(n){return n<10?"0"+n:n}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==="string"?c:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==="object"&&typeof value.toJSON==="function"){value=value.toJSON(key)}if(typeof rep==="function"){value=rep.call(holder,key,value)}switch(typeof value){case"string":return quote(value);case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==="[object Array]"){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||"null"}v=partial.length===0?"[]":gap?"[\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"]":"["+partial.join(",")+"]";gap=mind;return v}if(rep&&typeof rep==="object"){length=rep.length;for(i=0;i<length;i+=1){if(typeof rep[i]==="string"){k=rep[i];v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}else{for(k in value){if(Object.prototype.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}v=partial.length===0?"{}":gap?"{\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"}":"{"+partial.join(",")+"}";gap=mind;return v}}if(typeof JSON.stringify!=="function"){JSON.stringify=function(value,replacer,space){var i;gap="";indent="";if(typeof space==="number"){for(i=0;i<space;i+=1){indent+=" "}}else{if(typeof space==="string"){indent=space}}rep=replacer;if(replacer&&typeof replacer!=="function"&&(typeof replacer!=="object"||typeof replacer.length!=="number")){throw new Error("JSON.stringify")}return str("",{"":value})}}if(typeof JSON.parse!=="function"){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==="object"){for(k in value){if(Object.prototype.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v}else{delete value[k]}}}}return reviver.call(holder,key,value)}text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")}}}());/* */
|
114
|
+
|
115
|
+
/* base64.js */
|
116
|
+
var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";var b64padchar="=";function hex2b64(d){var b;var e;var a="";for(b=0;b+3<=d.length;b+=3){e=parseInt(d.substring(b,b+3),16);a+=b64map.charAt(e>>6)+b64map.charAt(e&63)}if(b+1==d.length){e=parseInt(d.substring(b,b+1),16);a+=b64map.charAt(e<<2)}else{if(b+2==d.length){e=parseInt(d.substring(b,b+2),16);a+=b64map.charAt(e>>2)+b64map.charAt((e&3)<<4)}}while((a.length&3)>0){a+=b64padchar}return a}function b64tohex(e){var c="";var d;var a=0;var b;for(d=0;d<e.length;++d){if(e.charAt(d)==b64padchar){break}v=b64map.indexOf(e.charAt(d));if(v<0){continue}if(a==0){c+=int2char(v>>2);b=v&3;a=1}else{if(a==1){c+=int2char((b<<2)|(v>>4));b=v&15;a=2}else{if(a==2){c+=int2char(b);c+=int2char(v>>2);b=v&3;a=3}else{c+=int2char((b<<2)|(v>>4));c+=int2char(v&15);a=0}}}}if(a==1){c+=int2char(b<<2)}return c}function b64toBA(e){var d=b64tohex(e);var c;var b=new Array();for(c=0;2*c<d.length;++c){b[c]=parseInt(d.substring(2*c,2*c+2),16)}return b};/* */
|
117
|
+
|
118
|
+
/* jsbn.js */
|
119
|
+
var dbits;var canary=244837814094590;var j_lm=((canary&16777215)==15715070);function BigInteger(e,d,f){if(e!=null){if("number"==typeof e){this.fromNumber(e,d,f)}else{if(d==null&&"string"!=typeof e){this.fromString(e,256)}else{this.fromString(e,d)}}}}function nbi(){return new BigInteger(null)}function am1(f,a,b,e,h,g){while(--g>=0){var d=a*this[f++]+b[e]+h;h=Math.floor(d/67108864);b[e++]=d&67108863}return h}function am2(f,q,r,e,o,a){var k=q&32767,p=q>>15;while(--a>=0){var d=this[f]&32767;var g=this[f++]>>15;var b=p*d+g*k;d=k*d+((b&32767)<<15)+r[e]+(o&1073741823);o=(d>>>30)+(b>>>15)+p*g+(o>>>30);r[e++]=d&1073741823}return o}function am3(f,q,r,e,o,a){var k=q&16383,p=q>>14;while(--a>=0){var d=this[f]&16383;var g=this[f++]>>14;var b=p*d+g*k;d=k*d+((b&16383)<<14)+r[e]+o;o=(d>>28)+(b>>14)+p*g;r[e++]=d&268435455}return o}if(j_lm&&(navigator.appName=="Microsoft Internet Explorer")){BigInteger.prototype.am=am2;dbits=30}else{if(j_lm&&(navigator.appName!="Netscape")){BigInteger.prototype.am=am1;dbits=26}else{BigInteger.prototype.am=am3;dbits=28}}BigInteger.prototype.DB=dbits;BigInteger.prototype.DM=((1<<dbits)-1);BigInteger.prototype.DV=(1<<dbits);var BI_FP=52;BigInteger.prototype.FV=Math.pow(2,BI_FP);BigInteger.prototype.F1=BI_FP-dbits;BigInteger.prototype.F2=2*dbits-BI_FP;var BI_RM="0123456789abcdefghijklmnopqrstuvwxyz";var BI_RC=new Array();var rr,vv;rr="0".charCodeAt(0);for(vv=0;vv<=9;++vv){BI_RC[rr++]=vv}rr="a".charCodeAt(0);for(vv=10;vv<36;++vv){BI_RC[rr++]=vv}rr="A".charCodeAt(0);for(vv=10;vv<36;++vv){BI_RC[rr++]=vv}function int2char(a){return BI_RM.charAt(a)}function intAt(b,a){var d=BI_RC[b.charCodeAt(a)];return(d==null)?-1:d}function bnpCopyTo(b){for(var a=this.t-1;a>=0;--a){b[a]=this[a]}b.t=this.t;b.s=this.s}function bnpFromInt(a){this.t=1;this.s=(a<0)?-1:0;if(a>0){this[0]=a}else{if(a<-1){this[0]=a+this.DV}else{this.t=0}}}function nbv(a){var b=nbi();b.fromInt(a);return b}function bnpFromString(h,c){var e;if(c==16){e=4}else{if(c==8){e=3}else{if(c==256){e=8}else{if(c==2){e=1}else{if(c==32){e=5}else{if(c==4){e=2}else{this.fromRadix(h,c);return}}}}}}this.t=0;this.s=0;var g=h.length,d=false,f=0;while(--g>=0){var a=(e==8)?h[g]&255:intAt(h,g);if(a<0){if(h.charAt(g)=="-"){d=true}continue}d=false;if(f==0){this[this.t++]=a}else{if(f+e>this.DB){this[this.t-1]|=(a&((1<<(this.DB-f))-1))<<f;this[this.t++]=(a>>(this.DB-f))}else{this[this.t-1]|=a<<f}}f+=e;if(f>=this.DB){f-=this.DB}}if(e==8&&(h[0]&128)!=0){this.s=-1;if(f>0){this[this.t-1]|=((1<<(this.DB-f))-1)<<f}}this.clamp();if(d){BigInteger.ZERO.subTo(this,this)}}function bnpClamp(){var a=this.s&this.DM;while(this.t>0&&this[this.t-1]==a){--this.t}}function bnToString(c){if(this.s<0){return"-"+this.negate().toString(c)}var e;if(c==16){e=4}else{if(c==8){e=3}else{if(c==2){e=1}else{if(c==32){e=5}else{if(c==4){e=2}else{return this.toRadix(c)}}}}}var g=(1<<e)-1,l,a=false,h="",f=this.t;var j=this.DB-(f*this.DB)%e;if(f-->0){if(j<this.DB&&(l=this[f]>>j)>0){a=true;h=int2char(l)}while(f>=0){if(j<e){l=(this[f]&((1<<j)-1))<<(e-j);l|=this[--f]>>(j+=this.DB-e)}else{l=(this[f]>>(j-=e))&g;if(j<=0){j+=this.DB;--f}}if(l>0){a=true}if(a){h+=int2char(l)}}}return a?h:"0"}function bnNegate(){var a=nbi();BigInteger.ZERO.subTo(this,a);return a}function bnAbs(){return(this.s<0)?this.negate():this}function bnCompareTo(b){var d=this.s-b.s;if(d!=0){return d}var c=this.t;d=c-b.t;if(d!=0){return(this.s<0)?-d:d}while(--c>=0){if((d=this[c]-b[c])!=0){return d}}return 0}function nbits(a){var c=1,b;if((b=a>>>16)!=0){a=b;c+=16}if((b=a>>8)!=0){a=b;c+=8}if((b=a>>4)!=0){a=b;c+=4}if((b=a>>2)!=0){a=b;c+=2}if((b=a>>1)!=0){a=b;c+=1}return c}function bnBitLength(){if(this.t<=0){return 0}return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM))}function bnpDLShiftTo(c,b){var a;for(a=this.t-1;a>=0;--a){b[a+c]=this[a]}for(a=c-1;a>=0;--a){b[a]=0}b.t=this.t+c;b.s=this.s}function bnpDRShiftTo(c,b){for(var a=c;a<this.t;++a){b[a-c]=this[a]}b.t=Math.max(this.t-c,0);b.s=this.s}function bnpLShiftTo(j,e){var b=j%this.DB;var a=this.DB-b;var g=(1<<a)-1;var f=Math.floor(j/this.DB),h=(this.s<<b)&this.DM,d;for(d=this.t-1;d>=0;--d){e[d+f+1]=(this[d]>>a)|h;h=(this[d]&g)<<b}for(d=f-1;d>=0;--d){e[d]=0}e[f]=h;e.t=this.t+f+1;e.s=this.s;e.clamp()}function bnpRShiftTo(g,d){d.s=this.s;var e=Math.floor(g/this.DB);if(e>=this.t){d.t=0;return}var b=g%this.DB;var a=this.DB-b;var f=(1<<b)-1;d[0]=this[e]>>b;for(var c=e+1;c<this.t;++c){d[c-e-1]|=(this[c]&f)<<a;d[c-e]=this[c]>>b}if(b>0){d[this.t-e-1]|=(this.s&f)<<a}d.t=this.t-e;d.clamp()}function bnpSubTo(d,f){var e=0,g=0,b=Math.min(d.t,this.t);while(e<b){g+=this[e]-d[e];f[e++]=g&this.DM;g>>=this.DB}if(d.t<this.t){g-=d.s;while(e<this.t){g+=this[e];f[e++]=g&this.DM;g>>=this.DB}g+=this.s}else{g+=this.s;while(e<d.t){g-=d[e];f[e++]=g&this.DM;g>>=this.DB}g-=d.s}f.s=(g<0)?-1:0;if(g<-1){f[e++]=this.DV+g}else{if(g>0){f[e++]=g}}f.t=e;f.clamp()}function bnpMultiplyTo(c,e){var b=this.abs(),f=c.abs();var d=b.t;e.t=d+f.t;while(--d>=0){e[d]=0}for(d=0;d<f.t;++d){e[d+b.t]=b.am(0,f[d],e,d,0,b.t)}e.s=0;e.clamp();if(this.s!=c.s){BigInteger.ZERO.subTo(e,e)}}function bnpSquareTo(d){var a=this.abs();var b=d.t=2*a.t;while(--b>=0){d[b]=0}for(b=0;b<a.t-1;++b){var e=a.am(b,a[b],d,2*b,0,1);if((d[b+a.t]+=a.am(b+1,2*a[b],d,2*b+1,e,a.t-b-1))>=a.DV){d[b+a.t]-=a.DV;d[b+a.t+1]=1}}if(d.t>0){d[d.t-1]+=a.am(b,a[b],d,2*b,0,1)}d.s=0;d.clamp()}function bnpDivRemTo(n,h,g){var w=n.abs();if(w.t<=0){return}var k=this.abs();if(k.t<w.t){if(h!=null){h.fromInt(0)}if(g!=null){this.copyTo(g)}return}if(g==null){g=nbi()}var d=nbi(),a=this.s,l=n.s;var v=this.DB-nbits(w[w.t-1]);if(v>0){w.lShiftTo(v,d);k.lShiftTo(v,g)}else{w.copyTo(d);k.copyTo(g)}var p=d.t;var b=d[p-1];if(b==0){return}var o=b*(1<<this.F1)+((p>1)?d[p-2]>>this.F2:0);var A=this.FV/o,z=(1<<this.F1)/o,x=1<<this.F2;var u=g.t,s=u-p,f=(h==null)?nbi():h;d.dlShiftTo(s,f);if(g.compareTo(f)>=0){g[g.t++]=1;g.subTo(f,g)}BigInteger.ONE.dlShiftTo(p,f);f.subTo(d,d);while(d.t<p){d[d.t++]=0}while(--s>=0){var c=(g[--u]==b)?this.DM:Math.floor(g[u]*A+(g[u-1]+x)*z);if((g[u]+=d.am(0,c,g,s,0,p))<c){d.dlShiftTo(s,f);g.subTo(f,g);while(g[u]<--c){g.subTo(f,g)}}}if(h!=null){g.drShiftTo(p,h);if(a!=l){BigInteger.ZERO.subTo(h,h)}}g.t=p;g.clamp();if(v>0){g.rShiftTo(v,g)}if(a<0){BigInteger.ZERO.subTo(g,g)}}function bnMod(b){var c=nbi();this.abs().divRemTo(b,null,c);if(this.s<0&&c.compareTo(BigInteger.ZERO)>0){b.subTo(c,c)}return c}function Classic(a){this.m=a}function cConvert(a){if(a.s<0||a.compareTo(this.m)>=0){return a.mod(this.m)}else{return a}}function cRevert(a){return a}function cReduce(a){a.divRemTo(this.m,null,a)}function cMulTo(a,c,b){a.multiplyTo(c,b);this.reduce(b)}function cSqrTo(a,b){a.squareTo(b);this.reduce(b)}Classic.prototype.convert=cConvert;Classic.prototype.revert=cRevert;Classic.prototype.reduce=cReduce;Classic.prototype.mulTo=cMulTo;Classic.prototype.sqrTo=cSqrTo;function bnpInvDigit(){if(this.t<1){return 0}var a=this[0];if((a&1)==0){return 0}var b=a&3;b=(b*(2-(a&15)*b))&15;b=(b*(2-(a&255)*b))&255;b=(b*(2-(((a&65535)*b)&65535)))&65535;b=(b*(2-a*b%this.DV))%this.DV;return(b>0)?this.DV-b:-b}function Montgomery(a){this.m=a;this.mp=a.invDigit();this.mpl=this.mp&32767;this.mph=this.mp>>15;this.um=(1<<(a.DB-15))-1;this.mt2=2*a.t}function montConvert(a){var b=nbi();a.abs().dlShiftTo(this.m.t,b);b.divRemTo(this.m,null,b);if(a.s<0&&b.compareTo(BigInteger.ZERO)>0){this.m.subTo(b,b)}return b}function montRevert(a){var b=nbi();a.copyTo(b);this.reduce(b);return b}function montReduce(a){while(a.t<=this.mt2){a[a.t++]=0}for(var c=0;c<this.m.t;++c){var b=a[c]&32767;var d=(b*this.mpl+(((b*this.mph+(a[c]>>15)*this.mpl)&this.um)<<15))&a.DM;b=c+this.m.t;a[b]+=this.m.am(0,d,a,c,0,this.m.t);while(a[b]>=a.DV){a[b]-=a.DV;a[++b]++}}a.clamp();a.drShiftTo(this.m.t,a);if(a.compareTo(this.m)>=0){a.subTo(this.m,a)}}function montSqrTo(a,b){a.squareTo(b);this.reduce(b)}function montMulTo(a,c,b){a.multiplyTo(c,b);this.reduce(b)}Montgomery.prototype.convert=montConvert;Montgomery.prototype.revert=montRevert;Montgomery.prototype.reduce=montReduce;Montgomery.prototype.mulTo=montMulTo;Montgomery.prototype.sqrTo=montSqrTo;function bnpIsEven(){return((this.t>0)?(this[0]&1):this.s)==0}function bnpExp(h,j){if(h>4294967295||h<1){return BigInteger.ONE}var f=nbi(),a=nbi(),d=j.convert(this),c=nbits(h)-1;d.copyTo(f);while(--c>=0){j.sqrTo(f,a);if((h&(1<<c))>0){j.mulTo(a,d,f)}else{var b=f;f=a;a=b}}return j.revert(f)}function bnModPowInt(b,a){var c;if(b<256||a.isEven()){c=new Classic(a)}else{c=new Montgomery(a)}return this.exp(b,c)}BigInteger.prototype.copyTo=bnpCopyTo;BigInteger.prototype.fromInt=bnpFromInt;BigInteger.prototype.fromString=bnpFromString;BigInteger.prototype.clamp=bnpClamp;BigInteger.prototype.dlShiftTo=bnpDLShiftTo;BigInteger.prototype.drShiftTo=bnpDRShiftTo;BigInteger.prototype.lShiftTo=bnpLShiftTo;BigInteger.prototype.rShiftTo=bnpRShiftTo;BigInteger.prototype.subTo=bnpSubTo;BigInteger.prototype.multiplyTo=bnpMultiplyTo;BigInteger.prototype.squareTo=bnpSquareTo;BigInteger.prototype.divRemTo=bnpDivRemTo;BigInteger.prototype.invDigit=bnpInvDigit;BigInteger.prototype.isEven=bnpIsEven;BigInteger.prototype.exp=bnpExp;BigInteger.prototype.toString=bnToString;BigInteger.prototype.negate=bnNegate;BigInteger.prototype.abs=bnAbs;BigInteger.prototype.compareTo=bnCompareTo;BigInteger.prototype.bitLength=bnBitLength;BigInteger.prototype.mod=bnMod;BigInteger.prototype.modPowInt=bnModPowInt;BigInteger.ZERO=nbv(0);BigInteger.ONE=nbv(1);/* */
|
120
|
+
|
121
|
+
/* prng4.js */
|
122
|
+
function Arcfour(){this.i=0;this.j=0;this.S=new Array}function ARC4init(c){var a,d,b;for(a=0;a<256;++a){this.S[a]=a}d=0;for(a=0;a<256;++a){d=d+this.S[a]+c[a%c.length]&255;b=this.S[a];this.S[a]=this.S[d];this.S[d]=b}this.i=0;this.j=0}function ARC4next(){var a;this.i=this.i+1&255;this.j=this.j+this.S[this.i]&255;a=this.S[this.i];this.S[this.i]=this.S[this.j];this.S[this.j]=a;return this.S[a+this.S[this.i]&255]}function prng_newstate(){return new Arcfour}Arcfour.prototype.init=ARC4init;Arcfour.prototype.next=ARC4next;var rng_psize=256;/* */
|
123
|
+
|
124
|
+
/* rng.js */
|
125
|
+
var rng_state;var rng_pool;var rng_pptr;function rng_seed_int(a){rng_pool[rng_pptr++]^=a&255;rng_pool[rng_pptr++]^=(a>>8)&255;rng_pool[rng_pptr++]^=(a>>16)&255;rng_pool[rng_pptr++]^=(a>>24)&255;if(rng_pptr>=rng_psize){rng_pptr-=rng_psize}}function rng_seed_time(){rng_seed_int(new Date().getTime())}if(rng_pool==null){rng_pool=[];rng_pptr=0;var t;try{if(window.crypto&&window.crypto.getRandomValues){var ua=new Uint8Array(32);window.crypto.getRandomValues(ua);for(t=0;t<32;++t){rng_pool[rng_pptr++]=ua[t]}}else{if(window.msCrypto&&window.msCrypto.getRandomValues){var ua=new Uint8Array(32);window.msCrypto.getRandomValues(ua);for(t=0;t<32;++t){rng_pool[rng_pptr++]=ua[t]}}else{if(window.crypto&&window.crypto.random){var z=window.crypto.random(32);for(t=0;t<z.length;++t){rng_pool[rng_pptr++]=z.charCodeAt(t)&255}}}}}catch(e){}while(rng_pptr<rng_psize){t=Math.floor(65536*Math.random());rng_pool[rng_pptr++]=t>>>8;rng_pool[rng_pptr++]=t&255}rng_pptr=0;rng_seed_time()}function rng_get_byte(){if(rng_state==null){rng_seed_time();rng_state=prng_newstate();rng_state.init(rng_pool);for(rng_pptr=0;rng_pptr<rng_pool.length;++rng_pptr){rng_pool[rng_pptr]=0}rng_pptr=0}return rng_state.next()}function rng_get_bytes(b){var a;for(a=0;a<b.length;++a){b[a]=rng_get_byte()}}function SecureRandom(){}SecureRandom.prototype.nextBytes=rng_get_bytes;/* */
|
126
|
+
|
127
|
+
/* rsa.js */
|
128
|
+
function parseBigInt(b,a){return new BigInteger(b,a)}function pkcs1pad2(c,g){if(g<c.length+11){alert("Message too long for RSA");return null}var f=new Array();var e=c.length-1;while(e>=0&&g>0){f[--g]=c[e--]}f[--g]=0;var d=new SecureRandom();var a=new Array();while(g>2){a[0]=0;while(a[0]==0){d.nextBytes(a)}f[--g]=a[0]}f[--g]=2;f[--g]=0;return new BigInteger(f)}function RSAKey(){this.n=null;this.e=0;this.d=null;this.p=null;this.q=null;this.dmp1=null;this.dmq1=null;this.coeff=null}function RSASetPublic(b,a){if(b!=null&&a!=null&&b.length>0&&a.length>0){this.n=parseBigInt(b,16);this.e=parseInt(a,16)}else{alert("Invalid RSA public key")}}function RSADoPublic(a){return a.modPowInt(this.e,this.n)}function RSAEncrypt(b){var a=pkcs1pad2(b,(this.n.bitLength()+7)>>3);if(a==null){return null}var e=this.doPublic(a);if(e==null){return null}var d=e.toString(16);if((d.length&1)==0){return d}else{return"0"+d}}function RSAEncryptB64(a){var b=this.encrypt(a);if(b){return hex2b64(b)}else{return null}}RSAKey.prototype.doPublic=RSADoPublic;RSAKey.prototype.setPublic=RSASetPublic;RSAKey.prototype.encrypt=RSAEncrypt;RSAKey.prototype.encrypt_b64=RSAEncryptB64;/* */
|
129
|
+
|
130
|
+
/* sjcl.js */
|
131
|
+
"use strict";function q(b){throw b}var r=void 0,t=!1;var sjcl={cipher:{},hash:{},keyexchange:{},mode:{},misc:{},codec:{},exception:{corrupt:function(b){this.toString=function(){return"CORRUPT: "+this.message};this.message=b},invalid:function(b){this.toString=function(){return"INVALID: "+this.message};this.message=b},bug:function(b){this.toString=function(){return"BUG: "+this.message};this.message=b},notReady:function(b){this.toString=function(){return"NOT READY: "+this.message};this.message=b}}};"undefined"!==typeof module&&module.exports&&(module.exports=sjcl);sjcl.cipher.aes=function(j){this.i[0][0][0]||this.v();var i,p,o,n,l=this.i[0][4],m=this.i[1];i=j.length;var k=1;4!==i&&(6!==i&&8!==i)&&q(new sjcl.exception.invalid("invalid aes key size"));this.b=[o=j.slice(0),n=[]];for(j=i;j<4*i+28;j++){p=o[j-1];if(0===j%i||8===i&&4===j%i){p=l[p>>>24]<<24^l[p>>16&255]<<16^l[p>>8&255]<<8^l[p&255],0===j%i&&(p=p<<8^p>>>24^k<<24,k=k<<1^283*(k>>7))}o[j]=o[j-i]^p}for(i=0;j;i++,j--){p=o[i&3?j:j-4],n[i]=4>=j||4>i?p:m[0][l[p>>>24]]^m[1][l[p>>16&255]]^m[2][l[p>>8&255]]^m[3][l[p&255]]}};sjcl.cipher.aes.prototype={encrypt:function(b){return y(this,b,0)},decrypt:function(b){return y(this,b,1)},i:[[[],[],[],[],[]],[[],[],[],[],[]]],v:function(){var R=this.i[0],Q=this.i[1],P=R[4],O=Q[4],N,w,x,v=[],u=[],s,i,o,j;for(N=0;256>N;N++){u[(v[N]=N<<1^283*(N>>7))^N]=N}for(w=x=0;!P[w];w^=s||1,x=u[x]||1){o=x^x<<1^x<<2^x<<3^x<<4;o=o>>8^o&255^99;P[w]=o;O[o]=w;i=v[N=v[s=v[w]]];j=16843009*i^65537*N^257*s^16843008*w;i=257*v[o]^16843008*o;for(N=0;4>N;N++){R[N][w]=i=i<<24^i>>>8,Q[N][o]=j=j<<24^j>>>8}}for(N=0;5>N;N++){R[N]=R[N].slice(0),Q[N]=Q[N].slice(0)}}};function y(ab,aa,Z){4!==aa.length&&q(new sjcl.exception.invalid("invalid aes block size"));var Y=ab.b[Z],X=aa[0]^Y[0],V=aa[Z?3:1]^Y[1],W=aa[2]^Y[2];aa=aa[Z?1:3]^Y[3];var U,T,S,P=Y.length/4-2,R,Q=4,o=[0,0,0,0];U=ab.i[Z];ab=U[0];var O=U[1],N=U[2],j=U[3],i=U[4];for(R=0;R<P;R++){U=ab[X>>>24]^O[V>>16&255]^N[W>>8&255]^j[aa&255]^Y[Q],T=ab[V>>>24]^O[W>>16&255]^N[aa>>8&255]^j[X&255]^Y[Q+1],S=ab[W>>>24]^O[aa>>16&255]^N[X>>8&255]^j[V&255]^Y[Q+2],aa=ab[aa>>>24]^O[X>>16&255]^N[V>>8&255]^j[W&255]^Y[Q+3],Q+=4,X=U,V=T,W=S}for(R=0;4>R;R++){o[Z?3&-R:R]=i[X>>>24]<<24^i[V>>16&255]<<16^i[W>>8&255]<<8^i[aa&255]^Y[Q++],U=X,X=V,V=W,W=aa,aa=U}return o}sjcl.bitArray={bitSlice:function(e,d,f){e=sjcl.bitArray.K(e.slice(d/32),32-(d&31)).slice(1);return f===r?e:sjcl.bitArray.clamp(e,f-d)},extract:function(f,e,h){var g=Math.floor(-e-h&31);return((e+h-1^e)&-32?f[e/32|0]<<32-g^f[e/32+1|0]>>>g:f[e/32|0]>>>g)&(1<<h)-1},concat:function(f,e){if(0===f.length||0===e.length){return f.concat(e)}var h=f[f.length-1],g=sjcl.bitArray.getPartial(h);return 32===g?f.concat(e):sjcl.bitArray.K(e,g,h|0,f.slice(0,f.length-1))},bitLength:function(d){var c=d.length;return 0===c?0:32*(c-1)+sjcl.bitArray.getPartial(d[c-1])},clamp:function(e,d){if(32*e.length<d){return e}e=e.slice(0,Math.ceil(d/32));var f=e.length;d&=31;0<f&&d&&(e[f-1]=sjcl.bitArray.partial(d,e[f-1]&2147483648>>d-1,1));return e},partial:function(e,d,f){return 32===e?d:(f?d|0:d<<32-e)+1099511627776*e},getPartial:function(b){return Math.round(b/1099511627776)||32},equal:function(f,e){if(sjcl.bitArray.bitLength(f)!==sjcl.bitArray.bitLength(e)){return t}var h=0,g;for(g=0;g<f.length;g++){h|=f[g]^e[g]}return 0===h},K:function(g,f,j,i){var h;h=0;for(i===r&&(i=[]);32<=f;f-=32){i.push(j),j=0}if(0===f){return i.concat(g)}for(h=0;h<g.length;h++){i.push(j|g[h]>>>f),j=g[h]<<32-f}h=g.length?g[g.length-1]:0;g=sjcl.bitArray.getPartial(h);i.push(sjcl.bitArray.partial(f+g&31,32<f+g?j:i.pop(),1));return i},M:function(d,c){return[d[0]^c[0],d[1]^c[1],d[2]^c[2],d[3]^c[3]]}};sjcl.codec.utf8String={fromBits:function(g){var f="",j=sjcl.bitArray.bitLength(g),i,h;for(i=0;i<j/8;i++){0===(i&3)&&(h=g[i/4]),f+=String.fromCharCode(h>>>24),h<<=8}return decodeURIComponent(escape(f))},toBits:function(f){f=unescape(encodeURIComponent(f));var e=[],h,g=0;for(h=0;h<f.length;h++){g=g<<8|f.charCodeAt(h),3===(h&3)&&(e.push(g),g=0)}h&3&&e.push(sjcl.bitArray.partial(8*(h&3),g));return e}};sjcl.codec.base64={C:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",fromBits:function(j,i,p){var o="",n=0,l=sjcl.codec.base64.C,m=0,k=sjcl.bitArray.bitLength(j);p&&(l=l.substr(0,62)+"-_");for(p=0;6*o.length<k;){o+=l.charAt((m^j[p]>>>n)>>>26),6>n?(m=j[p]<<6-n,n+=26,p++):(m<<=6,n-=6)}for(;o.length&3&&!i;){o+="="}return o},toBits:function(j,i){j=j.replace(/\s|=/g,"");var p=[],o,n=0,l=sjcl.codec.base64.C,m=0,k;i&&(l=l.substr(0,62)+"-_");for(o=0;o<j.length;o++){k=l.indexOf(j.charAt(o)),0>k&&q(new sjcl.exception.invalid("this isn't base64!")),26<n?(n-=26,p.push(m^k>>>n),m=k<<32-n):(n+=6,m^=k<<32-n)}n&56&&p.push(sjcl.bitArray.partial(n&56,m,1));return p}};sjcl.codec.base64url={fromBits:function(b){return sjcl.codec.base64.fromBits(b,1,1)},toBits:function(b){return sjcl.codec.base64.toBits(b,1)}};sjcl.codec.bytes={fromBits:function(g){var f=[],j=sjcl.bitArray.bitLength(g),i,h;for(i=0;i<j/8;i++){0===(i&3)&&(h=g[i/4]),f.push(h>>>24),h<<=8}return f},toBits:function(f){var e=[],h,g=0;for(h=0;h<f.length;h++){g=g<<8|f[h],3===(h&3)&&(e.push(g),g=0)}h&3&&e.push(sjcl.bitArray.partial(8*(h&3),g));return e}};sjcl.hash.sha256=function(b){this.b[0]||this.v();b?(this.n=b.n.slice(0),this.l=b.l.slice(0),this.f=b.f):this.reset()};sjcl.hash.sha256.hash=function(b){return(new sjcl.hash.sha256).update(b).finalize()};sjcl.hash.sha256.prototype={blockSize:512,reset:function(){this.n=this.I.slice(0);this.l=[];this.f=0;return this},update:function(e){"string"===typeof e&&(e=sjcl.codec.utf8String.toBits(e));var d,f=this.l=sjcl.bitArray.concat(this.l,e);d=this.f;e=this.f=d+sjcl.bitArray.bitLength(e);for(d=512+d&-512;d<=e;d+=512){z(this,f.splice(0,16))}return this},finalize:function(){var e,d=this.l,f=this.n,d=sjcl.bitArray.concat(d,[sjcl.bitArray.partial(1,1)]);for(e=d.length+2;e&15;e++){d.push(0)}d.push(Math.floor(this.f/4294967296));for(d.push(this.f|0);d.length;){z(this,d.splice(0,16))}this.reset();return f},I:[],b:[],v:function(){function f(b){return 4294967296*(b-Math.floor(b))|0}var e=0,h=2,g;f:for(;64>e;h++){for(g=2;g*g<=h;g++){if(0===h%g){continue f}}8>e&&(this.I[e]=f(Math.pow(h,0.5)));this.b[e]=f(Math.pow(h,1/3));e++}}};function z(U,T){var S,R,Q,O=T.slice(0),P=U.n,N=U.b,x=P[0],w=P[1],i=P[2],o=P[3],j=P[4],V=P[5],X=P[6],W=P[7];for(S=0;64>S;S++){16>S?R=O[S]:(R=O[S+1&15],Q=O[S+14&15],R=O[S&15]=(R>>>7^R>>>18^R>>>3^R<<25^R<<14)+(Q>>>17^Q>>>19^Q>>>10^Q<<15^Q<<13)+O[S&15]+O[S+9&15]|0),R=R+W+(j>>>6^j>>>11^j>>>25^j<<26^j<<21^j<<7)+(X^j&(V^X))+N[S],W=X,X=V,V=j,j=o+R|0,o=i,i=w,w=x,x=R+(w&i^o&(w^i))+(w>>>2^w>>>13^w>>>22^w<<30^w<<19^w<<10)|0}P[0]=P[0]+x|0;P[1]=P[1]+w|0;P[2]=P[2]+i|0;P[3]=P[3]+o|0;P[4]=P[4]+j|0;P[5]=P[5]+V|0;P[6]=P[6]+X|0;P[7]=P[7]+W|0}sjcl.mode.ccm={name:"ccm",encrypt:function(w,v,u,s,p){var n,o=v.slice(0),m=sjcl.bitArray,j=m.bitLength(u)/8,i=m.bitLength(o)/8;p=p||64;s=s||[];7>j&&q(new sjcl.exception.invalid("ccm: iv must be at least 7 bytes"));for(n=2;4>n&&i>>>8*n;n++){}n<15-j&&(n=15-j);u=m.clamp(u,8*(15-n));v=sjcl.mode.ccm.F(w,v,u,s,p,n);o=sjcl.mode.ccm.G(w,o,u,v,p,n);return m.concat(o.data,o.tag)},decrypt:function(w,v,u,s,p){p=p||64;s=s||[];var n=sjcl.bitArray,o=n.bitLength(u)/8,m=n.bitLength(v),j=n.clamp(v,m-p),i=n.bitSlice(v,m-p),m=(m-p)/8;7>o&&q(new sjcl.exception.invalid("ccm: iv must be at least 7 bytes"));for(v=2;4>v&&m>>>8*v;v++){}v<15-o&&(v=15-o);u=n.clamp(u,8*(15-v));j=sjcl.mode.ccm.G(w,j,u,i,p,v);w=sjcl.mode.ccm.F(w,j.data,u,s,p,v);n.equal(j.tag,w)||q(new sjcl.exception.corrupt("ccm: tag doesn't match"));return j.data},F:function(u,s,p,o,n,l){var m=[],j=sjcl.bitArray,i=j.M;n/=8;(n%2||4>n||16<n)&&q(new sjcl.exception.invalid("ccm: invalid tag length"));(4294967295<o.length||4294967295<s.length)&&q(new sjcl.exception.bug("ccm: can't deal with 4GiB or more data"));l=[j.partial(8,(o.length?64:0)|n-2<<2|l-1)];l=j.concat(l,p);l[3]|=j.bitLength(s)/8;l=u.encrypt(l);if(o.length){p=j.bitLength(o)/8;65279>=p?m=[j.partial(16,p)]:4294967295>=p&&(m=j.concat([j.partial(16,65534)],[p]));m=j.concat(m,o);for(o=0;o<m.length;o+=4){l=u.encrypt(i(l,m.slice(o,o+4).concat([0,0,0])))}}for(o=0;o<s.length;o+=4){l=u.encrypt(i(l,s.slice(o,o+4).concat([0,0,0])))}return j.clamp(l,8*n)},G:function(w,v,u,s,p,n){var o,m=sjcl.bitArray;o=m.M;var j=v.length,i=m.bitLength(v);u=m.concat([m.partial(8,n-1)],u).concat([0,0,0]).slice(0,4);s=m.bitSlice(o(s,w.encrypt(u)),0,p);if(!j){return{tag:s,data:[]}}for(o=0;o<j;o+=4){u[3]++,p=w.encrypt(u),v[o]^=p[0],v[o+1]^=p[1],v[o+2]^=p[2],v[o+3]^=p[3]}return{tag:s,data:m.clamp(v,i)}}};sjcl.misc.hmac=function(g,f){this.H=f=f||sjcl.hash.sha256;var j=[[],[]],i,h=f.prototype.blockSize/32;this.k=[new f,new f];g.length>h&&(g=f.hash(g));for(i=0;i<h;i++){j[0][i]=g[i]^909522486,j[1][i]=g[i]^1549556828}this.k[0].update(j[0]);this.k[1].update(j[1]);this.A=new f(this.k[0])};sjcl.misc.hmac.prototype.encrypt=sjcl.misc.hmac.prototype.mac=function(b){this.L&&q(new sjcl.exception.invalid("encrypt on already updated hmac called!"));this.update(b);return this.digest(b)};sjcl.misc.hmac.prototype.reset=function(){this.A=new this.H(this.k[0]);this.L=t};sjcl.misc.hmac.prototype.update=function(b){this.L=!0;this.A.update(b)};sjcl.misc.hmac.prototype.digest=function(){var b=this.A.finalize(),b=(new this.H(this.k[1])).update(b).finalize();this.reset();return b};sjcl.misc.pbkdf2=function(N,x,w,v,u){w=w||1000;(0>v||0>w)&&q(sjcl.exception.invalid("invalid params to pbkdf2"));"string"===typeof N&&(N=sjcl.codec.utf8String.toBits(N));"string"===typeof x&&(x=sjcl.codec.utf8String.toBits(x));u=u||sjcl.misc.hmac;N=new u(N);var o,s,n,m,j=[],i=sjcl.bitArray;for(m=1;32*j.length<(v||1);m++){u=o=N.encrypt(i.concat(x,[m]));for(s=1;s<w;s++){o=N.encrypt(o);for(n=0;n<o.length;n++){u[n]^=o[n]}}j=j.concat(u)}v&&(j=i.clamp(j,v));return j};sjcl.prng=function(b){this.c=[new sjcl.hash.sha256];this.g=[0];this.w=0;this.o={};this.u=0;this.D={};this.J=this.d=this.h=this.S=0;this.b=[0,0,0,0,0,0,0,0];this.e=[0,0,0,0];this.s=r;this.t=b;this.m=t;this.r={progress:{},seeded:{}};this.j=this.R=0;this.p=1;this.q=2;this.O=65536;this.B=[0,48,64,96,128,192,256,384,512,768,1024];this.P=30000;this.N=80};sjcl.prng.prototype={randomWords:function(i,h){var n=[],m;m=this.isReady(h);var l;m===this.j&&q(new sjcl.exception.notReady("generator isn't seeded"));if(m&this.q){m=!(m&this.p);l=[];var j=0,k;this.J=l[0]=(new Date).valueOf()+this.P;for(k=0;16>k;k++){l.push(4294967296*Math.random()|0)}for(k=0;k<this.c.length&&!(l=l.concat(this.c[k].finalize()),j+=this.g[k],this.g[k]=0,!m&&this.w&1<<k);k++){}this.w>=1<<this.c.length&&(this.c.push(new sjcl.hash.sha256),this.g.push(0));this.d-=j;j>this.h&&(this.h=j);this.w++;this.b=sjcl.hash.sha256.hash(this.b.concat(l));this.s=new sjcl.cipher.aes(this.b);for(m=0;4>m&&!(this.e[m]=this.e[m]+1|0,this.e[m]);m++){}}for(m=0;m<i;m+=4){0===(m+1)%this.O&&A(this),l=B(this),n.push(l[0],l[1],l[2],l[3])}A(this);return n.slice(0,i)},setDefaultParanoia:function(d,c){0===d&&"Setting paranoia=0 will ruin your security; use it only for testing"!==c&&q("Setting paranoia=0 will ruin your security; use it only for testing");this.t=d},addEntropy:function(u,s,p){p=p||"user";var o,n,l=(new Date).valueOf(),m=this.o[p],j=this.isReady(),i=0;o=this.D[p];o===r&&(o=this.D[p]=this.S++);m===r&&(m=this.o[p]=0);this.o[p]=(this.o[p]+1)%this.c.length;switch(typeof u){case"number":s===r&&(s=1);this.c[m].update([o,this.u++,1,s,l,1,u|0]);break;case"object":p=Object.prototype.toString.call(u);if("[object Uint32Array]"===p){n=[];for(p=0;p<u.length;p++){n.push(u[p])}u=n}else{"[object Array]"!==p&&(i=1);for(p=0;p<u.length&&!i;p++){"number"!==typeof u[p]&&(i=1)}}if(!i){if(s===r){for(p=s=0;p<u.length;p++){for(n=u[p];0<n;){s++,n>>>=1}}}this.c[m].update([o,this.u++,2,s,l,u.length].concat(u))}break;case"string":s===r&&(s=u.length);this.c[m].update([o,this.u++,3,s,l,u.length]);this.c[m].update(u);break;default:i=1}i&&q(new sjcl.exception.bug("random: addEntropy only supports number, array of numbers or string"));this.g[m]+=s;this.d+=s;j===this.j&&(this.isReady()!==this.j&&C("seeded",Math.max(this.h,this.d)),C("progress",this.getProgress()))},isReady:function(b){b=this.B[b!==r?b:this.t];return this.h&&this.h>=b?this.g[0]>this.N&&(new Date).valueOf()>this.J?this.q|this.p:this.p:this.d>=b?this.q|this.j:this.j},getProgress:function(b){b=this.B[b?b:this.t];return this.h>=b?1:this.d>b?1:this.d/b},startCollectors:function(){this.m||(this.a={loadTimeCollector:D(this,this.U),mouseCollector:D(this,this.V),keyboardCollector:D(this,this.T),accelerometerCollector:D(this,this.Q)},window.addEventListener?(window.addEventListener("load",this.a.loadTimeCollector,t),window.addEventListener("mousemove",this.a.mouseCollector,t),window.addEventListener("keypress",this.a.keyboardCollector,t),window.addEventListener("devicemotion",this.a.accelerometerCollector,t)):document.attachEvent?(document.attachEvent("onload",this.a.loadTimeCollector),document.attachEvent("onmousemove",this.a.mouseCollector),document.attachEvent("keypress",this.a.keyboardCollector)):q(new sjcl.exception.bug("can't attach event")),this.m=!0)},stopCollectors:function(){this.m&&(window.removeEventListener?(window.removeEventListener("load",this.a.loadTimeCollector,t),window.removeEventListener("mousemove",this.a.mouseCollector,t),window.removeEventListener("keypress",this.a.keyboardCollector,t),window.removeEventListener("devicemotion",this.a.accelerometerCollector,t)):document.detachEvent&&(document.detachEvent("onload",this.a.loadTimeCollector),document.detachEvent("onmousemove",this.a.mouseCollector),document.detachEvent("keypress",this.a.keyboardCollector)),this.m=t)},addEventListener:function(d,c){this.r[d][this.R++]=c},removeEventListener:function(h,f){var l,k,j=this.r[h],i=[];for(k in j){j.hasOwnProperty(k)&&j[k]===f&&i.push(k)}for(l=0;l<i.length;l++){k=i[l],delete j[k]}},T:function(){E(1)},V:function(b){sjcl.random.addEntropy([b.x||b.clientX||b.offsetX||0,b.y||b.clientY||b.offsetY||0],2,"mouse");E(0)},U:function(){E(2)},Q:function(d){d=d.accelerationIncludingGravity.x||d.accelerationIncludingGravity.y||d.accelerationIncludingGravity.z;if(window.orientation){var c=window.orientation;"number"===typeof c&&sjcl.random.addEntropy(c,1,"accelerometer")}d&&sjcl.random.addEntropy(d,2,"accelerometer");E(0)}};function C(g,f){var j,i=sjcl.random.r[g],h=[];for(j in i){i.hasOwnProperty(j)&&h.push(i[j])}for(j=0;j<h.length;j++){h[j](f)}}function E(b){window&&window.performance&&"function"===typeof window.performance.now?sjcl.random.addEntropy(window.performance.now(),b,"loadtime"):sjcl.random.addEntropy((new Date).valueOf(),b,"loadtime")}function A(b){b.b=B(b).concat(B(b));b.s=new sjcl.cipher.aes(b.b)}function B(d){for(var c=0;4>c&&!(d.e[c]=d.e[c]+1|0,d.e[c]);c++){}return d.s.encrypt(d.e)}function D(d,c){return function(){c.apply(d,arguments)}}sjcl.random=new sjcl.prng(6);a:try{var F,G,H,I;if(I="undefined"!==typeof module){var J;if(J=module.exports){var K;try{K=require("crypto")}catch(L){K=null}J=(G=K)&&G.randomBytes}I=J}if(I){F=G.randomBytes(128),F=new Uint32Array((new Uint8Array(F)).buffer),sjcl.random.addEntropy(F,1024,"crypto['randomBytes']")}else{if(window&&Uint32Array){H=new Uint32Array(32);if(window.crypto&&window.crypto.getRandomValues){window.crypto.getRandomValues(H)}else{if(window.msCrypto&&window.msCrypto.getRandomValues){window.msCrypto.getRandomValues(H)}else{break a}}sjcl.random.addEntropy(H,1024,"crypto['getRandomValues']")}}}catch(M){"undefined"!==typeof window&&window.console&&(console.log("There was an error collecting entropy from the browser:"),console.log(M))};/* */
|
132
|
+
|
133
|
+
/* adyen */
|
134
|
+
var adyen = window.adyen = window.adyen || {};
|
135
|
+
|
136
|
+
var encrypt = adyen.encrypt = adyen.encrypt || {
|
137
|
+
createEncryptedForm : function(form, key, options) {
|
138
|
+
return new EncryptedForm(form, key, options);
|
139
|
+
}
|
140
|
+
};
|
141
|
+
|
142
|
+
encrypt.errors = encrypt.errors || {};
|
143
|
+
encrypt.errors.UNABLETOBIND = 'CSEB01';
|
144
|
+
|
145
|
+
function addEvent(element, event, callback, capture) {
|
146
|
+
if (typeof element.addEventListener === 'function') {
|
147
|
+
element.addEventListener(event, callback, capture);
|
148
|
+
} else if (element.attachEvent) {
|
149
|
+
element.attachEvent('on' + event, callback);
|
150
|
+
} else {
|
151
|
+
throw new Error(encrypt.errors.UNABLETOBIND + ": Unable to bind " + event + "-event");
|
152
|
+
}
|
153
|
+
}
|
154
|
+
|
155
|
+
function hasClass(elem, className) {
|
156
|
+
return elem && new RegExp(' ' + className + ' ').test(' ' + (elem.className || '') + ' ');
|
157
|
+
}
|
158
|
+
|
159
|
+
function addClass(elem, className) {
|
160
|
+
if (!elem) {
|
161
|
+
return;
|
162
|
+
}
|
163
|
+
if (!hasClass(elem, className)) {
|
164
|
+
elem.className += ' ' + className;
|
165
|
+
}
|
166
|
+
}
|
167
|
+
|
168
|
+
function removeClass(elem, className) {
|
169
|
+
if (!elem) {
|
170
|
+
return;
|
171
|
+
}
|
172
|
+
var newClass = ' ' + elem.className.replace(/[\t\r\n]/g, ' ') + ' ';
|
173
|
+
if (hasClass(elem, className)) {
|
174
|
+
while (newClass.indexOf(' ' + className + ' ') >= 0) {
|
175
|
+
newClass = newClass.replace(' ' + className + ' ', ' ');
|
176
|
+
}
|
177
|
+
elem.className = newClass.replace(/^\s+|\s+$/g, '');
|
178
|
+
}
|
179
|
+
}
|
180
|
+
|
181
|
+
function getAttribute(node, attribute, defaultValue) {
|
182
|
+
if (node && node.getAttribute) {
|
183
|
+
return node.getAttribute(attribute) || defaultValue;
|
184
|
+
} else {
|
185
|
+
return defaultValue;
|
186
|
+
}
|
187
|
+
}
|
188
|
+
|
189
|
+
encrypt.version = '0_1_7';
|
190
|
+
|
191
|
+
/*
|
192
|
+
* Compatibility JavaScript older than 1.8.5 (IE8, IE7)
|
193
|
+
*
|
194
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
|
195
|
+
*/
|
196
|
+
if (!Function.prototype.bind) {
|
197
|
+
Function.prototype.bind = function(oThis) {
|
198
|
+
if (typeof this !== "function") {
|
199
|
+
// closest thing possible to the ECMAScript 5 internal
|
200
|
+
// IsCallable function
|
201
|
+
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
|
202
|
+
}
|
203
|
+
var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function() {
|
204
|
+
}, fBound = function() {
|
205
|
+
return fToBind.apply(this instanceof fNOP && oThis ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
|
206
|
+
};
|
207
|
+
|
208
|
+
fNOP.prototype = this.prototype;
|
209
|
+
fBound.prototype = new fNOP();
|
210
|
+
|
211
|
+
return fBound;
|
212
|
+
};
|
213
|
+
}
|
214
|
+
|
215
|
+
/*
|
216
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString
|
217
|
+
*/
|
218
|
+
if ( !Date.prototype.toISOString ) {
|
219
|
+
( function() {
|
220
|
+
|
221
|
+
function pad(number) {
|
222
|
+
if ( number < 10 ) {
|
223
|
+
return '0' + number;
|
224
|
+
}
|
225
|
+
return number;
|
226
|
+
}
|
227
|
+
|
228
|
+
Date.prototype.toISOString = function() {
|
229
|
+
return this.getUTCFullYear() +
|
230
|
+
'-' + pad( this.getUTCMonth() + 1 ) +
|
231
|
+
'-' + pad( this.getUTCDate() ) +
|
232
|
+
'T' + pad( this.getUTCHours() ) +
|
233
|
+
':' + pad( this.getUTCMinutes() ) +
|
234
|
+
':' + pad( this.getUTCSeconds() ) +
|
235
|
+
'.' + (this.getUTCMilliseconds() / 1000).toFixed(3).slice(2, 5) +
|
236
|
+
'Z';
|
237
|
+
};
|
238
|
+
|
239
|
+
} () );
|
240
|
+
}
|
241
|
+
|
242
|
+
/*
|
243
|
+
* Wrapped in closure to prevent external manipulation;
|
244
|
+
*/
|
245
|
+
var validations = {};
|
246
|
+
|
247
|
+
/***************************************************************************
|
248
|
+
* boolean luhnCheck([String CardNumber]) return true if CardNumber pass the
|
249
|
+
* luhn check else return false. Reference:
|
250
|
+
* http://www.ling.nwu.edu/~sburke/pub/luhn_lib.pl \
|
251
|
+
**************************************************************************/
|
252
|
+
validations.luhnCheck = function() {
|
253
|
+
var argv = arguments;
|
254
|
+
var argc = arguments.length;
|
255
|
+
|
256
|
+
var CardNumber = argc > 0 ? argv[0] : this.cardnumber;
|
257
|
+
|
258
|
+
if (isNaN(parseInt(CardNumber, 10))) {
|
259
|
+
return false;
|
260
|
+
}
|
261
|
+
|
262
|
+
var no_digit = CardNumber.length;
|
263
|
+
var oddoeven = no_digit & 1;
|
264
|
+
var sum = 0;
|
265
|
+
|
266
|
+
for (var count = 0; count < no_digit; count++) {
|
267
|
+
var digit = parseInt(CardNumber.charAt(count), 10);
|
268
|
+
if (!((count & 1) ^ oddoeven)) {
|
269
|
+
digit *= 2;
|
270
|
+
if (digit > 9)
|
271
|
+
digit -= 9;
|
272
|
+
}
|
273
|
+
sum += digit;
|
274
|
+
}
|
275
|
+
|
276
|
+
if (sum % 10 === 0) {
|
277
|
+
return true;
|
278
|
+
} else {
|
279
|
+
return false;
|
280
|
+
}
|
281
|
+
};
|
282
|
+
|
283
|
+
validations.cvcCheck = function(val) {
|
284
|
+
return val && val.match && val.match(/^\d{3,4}$/);
|
285
|
+
};
|
286
|
+
|
287
|
+
validations.createChangeHandler = function(cse, type, allowEmpty) {
|
288
|
+
return function(ev) {
|
289
|
+
var node = ev.target || ev.srcElement, val = (node || {}).value || '', field = getAttribute(node, 'data-encrypted-name');
|
290
|
+
|
291
|
+
if (cse.options[field + 'IgnoreNonNumeric']) {
|
292
|
+
val = val.replace(/\D/g, '');
|
293
|
+
}
|
294
|
+
|
295
|
+
if (validations[type + 'Check'](val)) {
|
296
|
+
cse.validity[type] = true;
|
297
|
+
removeClass(node, 'invalid-' + type);
|
298
|
+
addClass(node, 'valid-' + type);
|
299
|
+
} else {
|
300
|
+
cse.validity[type] = false;
|
301
|
+
addClass(node, 'invalid-' + type);
|
302
|
+
removeClass(node, 'valid-' + type);
|
303
|
+
}
|
304
|
+
if (allowEmpty && val === '') {
|
305
|
+
removeClass(node, 'valid-' + type);
|
306
|
+
removeClass(node, 'invalid-' + type);
|
307
|
+
}
|
308
|
+
cse.toggleSubmit();
|
309
|
+
};
|
310
|
+
};
|
311
|
+
|
312
|
+
/*
|
313
|
+
* @constructor EncryptedForm
|
314
|
+
*
|
315
|
+
* @param element {DOMNode} The form element to encrypt as a DOMNode (
|
316
|
+
* <form> ); @param key {String} The public key used to communicate with
|
317
|
+
* Adyen @param [options] {Object} Options to pass to the constructor (
|
318
|
+
* onsubmit {Function} and name {String} )
|
319
|
+
*
|
320
|
+
* @return form {EncryptedForm} The instance of EncryptedForm.
|
321
|
+
*
|
322
|
+
*/
|
323
|
+
|
324
|
+
var EncryptedForm = encrypt.EncryptedForm = function(element, key, options) {
|
325
|
+
|
326
|
+
try {
|
327
|
+
sjcl.random.startCollectors();
|
328
|
+
} catch (e) {
|
329
|
+
// what to do?
|
330
|
+
}
|
331
|
+
|
332
|
+
if (typeof element !== 'object' || typeof element.ownerDocument !== 'object') {
|
333
|
+
|
334
|
+
throw new Error('Expected target element to be a HTML Form element');
|
335
|
+
}
|
336
|
+
|
337
|
+
if ('form' !== (element.nodeName || element.tagName || '').toLowerCase()) {
|
338
|
+
throw new Error('Expected target element to be a HTML Form element');
|
339
|
+
}
|
340
|
+
|
341
|
+
// element and public key
|
342
|
+
this.element = element;
|
343
|
+
this.key = key;
|
344
|
+
this.validity = {};
|
345
|
+
|
346
|
+
// create an empty object if options don't exist
|
347
|
+
this.options = options = options || {};
|
348
|
+
|
349
|
+
if (typeof options !== 'object') {
|
350
|
+
throw new Error('Expected options to be an object');
|
351
|
+
}
|
352
|
+
|
353
|
+
// Defaults
|
354
|
+
if (typeof options.numberIgnoreNonNumeric === "undefined") {
|
355
|
+
options.numberIgnoreNonNumeric = true;
|
356
|
+
}
|
357
|
+
|
358
|
+
this.name = options.name || 'adyen-encrypted-data';
|
359
|
+
this.onsubmit = options.onsubmit || function() {
|
360
|
+
};
|
361
|
+
|
362
|
+
if (this.element.addEventListener) {
|
363
|
+
this.element.addEventListener('submit', this.handleSubmit.bind(this), false);
|
364
|
+
} else if (this.element.attachEvent) {
|
365
|
+
this.element.attachEvent('onsubmit', this.handleSubmit.bind(this));
|
366
|
+
}
|
367
|
+
|
368
|
+
if (options.enableValidations !== false) {
|
369
|
+
this.addValidations();
|
370
|
+
}
|
371
|
+
|
372
|
+
};
|
373
|
+
|
374
|
+
EncryptedForm.prototype = {
|
375
|
+
|
376
|
+
constructor : EncryptedForm,
|
377
|
+
|
378
|
+
/*
|
379
|
+
*
|
380
|
+
* Compatibility wrapper for lte IE8. We create the wrapper once, rather
|
381
|
+
* than doing the test on each childNode.
|
382
|
+
*
|
383
|
+
* @param node {DOMNode} @param attrName {String}
|
384
|
+
*
|
385
|
+
*/
|
386
|
+
hasAttribute : document.documentElement.hasAttribute ? function(node, attrName) {
|
387
|
+
// Native support
|
388
|
+
return node.hasAttribute(attrName);
|
389
|
+
} : function(node, attrName) {
|
390
|
+
// IE7, IE8
|
391
|
+
return node.attributes && node.attributes[attrName];
|
392
|
+
},
|
393
|
+
|
394
|
+
/*
|
395
|
+
*
|
396
|
+
* Handles a submit of the form. It creates a hidden input with the form
|
397
|
+
* data as serialized, encrypted JSON.
|
398
|
+
*
|
399
|
+
* @param e {Event} The submit event to handle.
|
400
|
+
*
|
401
|
+
*/
|
402
|
+
|
403
|
+
handleSubmit : function(e) {
|
404
|
+
|
405
|
+
if (this.options.enableValidations !== false) {
|
406
|
+
if (!this.isValid()) {
|
407
|
+
if (e.preventDefault) {
|
408
|
+
e.preventDefault();
|
409
|
+
}
|
410
|
+
// IE7 and lower
|
411
|
+
if (window.event) {
|
412
|
+
window.event.returnValue = false;
|
413
|
+
}
|
414
|
+
if (e.originalEvent) {
|
415
|
+
e.originalEvent.returnValue = false;
|
416
|
+
}
|
417
|
+
e.returnValue = false;
|
418
|
+
|
419
|
+
return false;
|
420
|
+
}
|
421
|
+
}
|
422
|
+
|
423
|
+
this.createEncryptedField(this.encrypt());
|
424
|
+
|
425
|
+
this.onsubmit(e);
|
426
|
+
},
|
427
|
+
|
428
|
+
/*
|
429
|
+
* Creates an RSA key based on the public key.
|
430
|
+
*
|
431
|
+
* @returns rsa {RSAKey} An RSAKey based on the public key provided.
|
432
|
+
*
|
433
|
+
*/
|
434
|
+
|
435
|
+
createRSAKey : function() {
|
436
|
+
|
437
|
+
var k = this.key.split('|');
|
438
|
+
|
439
|
+
if (k.length != 2) {
|
440
|
+
throw 'Malformed public key';
|
441
|
+
}
|
442
|
+
|
443
|
+
var exp = k[0];
|
444
|
+
var mod = k[1];
|
445
|
+
|
446
|
+
// would be better to put it in a package.
|
447
|
+
var rsa = new RSAKey();
|
448
|
+
rsa.setPublic(mod, exp);
|
449
|
+
|
450
|
+
return rsa;
|
451
|
+
|
452
|
+
},
|
453
|
+
|
454
|
+
/*
|
455
|
+
* Creates an AES key.
|
456
|
+
*
|
457
|
+
* @returns aes {Object} An AESKey with encryption methods.
|
458
|
+
*
|
459
|
+
*/
|
460
|
+
|
461
|
+
createAESKey : function() {
|
462
|
+
return new AESKey();
|
463
|
+
},
|
464
|
+
|
465
|
+
/*
|
466
|
+
* Gets all encrypted fields from a root node ( usually the form element ).
|
467
|
+
*
|
468
|
+
* @param node {DOMNode} The root of the form to get encrypted fields
|
469
|
+
* from ( i.e. querySelectorAll( '[data-encrypeted-name]' ) ). @param
|
470
|
+
* [fields] {Array} An array of fields ( used when recursively looking
|
471
|
+
* up children ).
|
472
|
+
*
|
473
|
+
* @returns fields {Array} An array of fields with a
|
474
|
+
* data-encrypeted-name attribute. ( Alternatively returns a DOMNodeList ).
|
475
|
+
*
|
476
|
+
*/
|
477
|
+
|
478
|
+
getEncryptedFields : function(node, fields) {
|
479
|
+
|
480
|
+
if (node.querySelectorAll) {
|
481
|
+
return node.querySelectorAll('[data-encrypted-name]');
|
482
|
+
}
|
483
|
+
|
484
|
+
fields = fields || [];
|
485
|
+
|
486
|
+
var children = node.children;
|
487
|
+
var child;
|
488
|
+
|
489
|
+
for (var i = 0; i < children.length; i++) {
|
490
|
+
child = children[i];
|
491
|
+
|
492
|
+
if (this.hasAttribute(child, 'data-encrypted-name')) {
|
493
|
+
fields.push(child);
|
494
|
+
} else {
|
495
|
+
this.getEncryptedFields(child, fields);
|
496
|
+
}
|
497
|
+
|
498
|
+
}
|
499
|
+
|
500
|
+
return fields;
|
501
|
+
|
502
|
+
},
|
503
|
+
|
504
|
+
/*
|
505
|
+
* Creates JSON object
|
506
|
+
*
|
507
|
+
* @param fields {Array} An array of fields to convert to JSON.
|
508
|
+
*
|
509
|
+
* @return data {JSON} The data as JavaScript Object Notation
|
510
|
+
*
|
511
|
+
*/
|
512
|
+
|
513
|
+
toJSON : function(fields) {
|
514
|
+
|
515
|
+
var field;
|
516
|
+
|
517
|
+
var data = {};
|
518
|
+
var key, value;
|
519
|
+
|
520
|
+
for (var i = fields.length - 1; i >= 0; i--) {
|
521
|
+
|
522
|
+
field = fields[i];
|
523
|
+
|
524
|
+
field.removeAttribute('name');
|
525
|
+
key = field.getAttribute('data-encrypted-name');
|
526
|
+
value = field.value;
|
527
|
+
|
528
|
+
data[key] = value;
|
529
|
+
|
530
|
+
}
|
531
|
+
|
532
|
+
return data;
|
533
|
+
|
534
|
+
},
|
535
|
+
|
536
|
+
/*
|
537
|
+
* Encrypts data
|
538
|
+
*
|
539
|
+
* @return data {String} The data in the form as encrypted and
|
540
|
+
* serialized JSON.
|
541
|
+
*
|
542
|
+
*/
|
543
|
+
|
544
|
+
encrypt : function() {
|
545
|
+
|
546
|
+
var data = this.toJSON(this.getEncryptedFields(this.element));
|
547
|
+
|
548
|
+
var rsa, aes, cipher, encoded, encrypted, prefix;
|
549
|
+
|
550
|
+
rsa = this.createRSAKey();
|
551
|
+
aes = this.createAESKey();
|
552
|
+
|
553
|
+
cipher = aes.encrypt(JSON.stringify(data));
|
554
|
+
keybytes = sjcl.codec.bytes.fromBits(aes.key);
|
555
|
+
encrypted = rsa.encrypt_b64(keybytes);
|
556
|
+
prefix = 'adyenjs_' + encrypt.version + '$';
|
557
|
+
|
558
|
+
return [ prefix, encrypted, '$', cipher ].join('');
|
559
|
+
|
560
|
+
},
|
561
|
+
|
562
|
+
/*
|
563
|
+
*
|
564
|
+
* Creates an encrypted field.
|
565
|
+
*
|
566
|
+
* @param data {String} The data in the form as encrypted and serialized
|
567
|
+
* JSON.
|
568
|
+
*
|
569
|
+
*/
|
570
|
+
|
571
|
+
createEncryptedField : function(data) {
|
572
|
+
|
573
|
+
var element = document.getElementById(this.name);
|
574
|
+
|
575
|
+
if (!element) {
|
576
|
+
element = document.createElement('input');
|
577
|
+
element.type = 'hidden';
|
578
|
+
element.name = element.id = this.name;
|
579
|
+
this.element.appendChild(element);
|
580
|
+
}
|
581
|
+
|
582
|
+
element.setAttribute('value', data);
|
583
|
+
|
584
|
+
},
|
585
|
+
|
586
|
+
addValidations : function() {
|
587
|
+
|
588
|
+
var cse = this, elements = this.element.elements, c = elements.length, element, handlers = {};
|
589
|
+
|
590
|
+
for (; c-- > 0;) {
|
591
|
+
element = elements[c];
|
592
|
+
if (!element || !element.getAttribute) {
|
593
|
+
continue;
|
594
|
+
} else if (element.getAttribute('data-encrypted-name') === 'number') {
|
595
|
+
handlers.luhnHandler = handlers.luhnHandler || validations.createChangeHandler(cse, 'luhn', true);
|
596
|
+
addEvent(element, 'change', handlers.luhnHandler, false);
|
597
|
+
handlers.luhnHandler({
|
598
|
+
target : element
|
599
|
+
});
|
600
|
+
} else if (element.getAttribute('data-encrypted-name') === 'cvc') {
|
601
|
+
handlers.cvcHandler = handlers.cvcHandler || validations.createChangeHandler(cse, 'cvc', true);
|
602
|
+
addEvent(element, 'change', handlers.cvcHandler, false);
|
603
|
+
handlers.cvcHandler({
|
604
|
+
target : element
|
605
|
+
});
|
606
|
+
}
|
607
|
+
}
|
608
|
+
},
|
609
|
+
|
610
|
+
isValid : function() {
|
611
|
+
var valid = true, elements = this.element.elements, enabled;
|
612
|
+
|
613
|
+
for ( var i in this.validity) {
|
614
|
+
if (this.validity.hasOwnProperty(i)) {
|
615
|
+
valid = valid && this.validity[i];
|
616
|
+
}
|
617
|
+
}
|
618
|
+
|
619
|
+
return valid;
|
620
|
+
},
|
621
|
+
|
622
|
+
toggleSubmit : function() {
|
623
|
+
|
624
|
+
var valid = this.isValid(), elements = this.element.elements, enabled;
|
625
|
+
|
626
|
+
enabled = valid === true || (this.options && this.options.submitButtonAlwaysEnabled === true);
|
627
|
+
|
628
|
+
for (var c = elements.length; c-- > 0;) {
|
629
|
+
if (elements[c] && (elements[c].type || '').toLowerCase() === 'submit') {
|
630
|
+
elements[c].disabled = !enabled;
|
631
|
+
}
|
632
|
+
}
|
633
|
+
|
634
|
+
return valid;
|
635
|
+
|
636
|
+
}
|
637
|
+
|
638
|
+
};
|
639
|
+
|
640
|
+
/*
|
641
|
+
*
|
642
|
+
* @constructor AESKey
|
643
|
+
*
|
644
|
+
* @return aes {AESKey} An AESKey with encryption methods.
|
645
|
+
*
|
646
|
+
*/
|
647
|
+
|
648
|
+
var AESKey = function() {
|
649
|
+
// empty constructor
|
650
|
+
};
|
651
|
+
|
652
|
+
AESKey.prototype = {
|
653
|
+
|
654
|
+
constructor : AESKey,
|
655
|
+
|
656
|
+
key : sjcl.random.randomWords(8, 0),
|
657
|
+
|
658
|
+
encrypt : function(text) {
|
659
|
+
|
660
|
+
return this.encryptWithIv(text, sjcl.random.randomWords(3, 0));
|
661
|
+
|
662
|
+
},
|
663
|
+
|
664
|
+
encryptWithIv : function(text, iv) {
|
665
|
+
|
666
|
+
var aes, bits, cipher, cipherIV;
|
667
|
+
|
668
|
+
aes = new sjcl.cipher.aes(this.key);
|
669
|
+
bits = sjcl.codec.utf8String.toBits(text);
|
670
|
+
cipher = sjcl.mode.ccm.encrypt(aes, bits, iv);
|
671
|
+
cipherIV = sjcl.bitArray.concat(iv, cipher);
|
672
|
+
|
673
|
+
return sjcl.codec.base64.fromBits(cipherIV);
|
674
|
+
|
675
|
+
}
|
676
|
+
|
677
|
+
};
|
678
|
+
|
679
|
+
})();
|