Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/third_party/closure/goog/crypt/arc4.js
2868 views
1
// Copyright 2005 The Closure Library Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS-IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
/**
16
* @fileoverview ARC4 streamcipher implementation. A description of the
17
* algorithm can be found at:
18
* http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt.
19
*
20
* Usage:
21
* <code>
22
* var arc4 = new goog.crypt.Arc4();
23
* arc4.setKey(key);
24
* arc4.discard(1536);
25
* arc4.crypt(bytes);
26
* </code>
27
*
28
* Note: For converting between strings and byte arrays, goog.crypt.base64 may
29
* be useful.
30
*
31
*/
32
33
goog.provide('goog.crypt.Arc4');
34
35
goog.require('goog.asserts');
36
37
38
39
/**
40
* ARC4 streamcipher implementation.
41
* @constructor
42
* @final
43
* @struct
44
*/
45
goog.crypt.Arc4 = function() {
46
/**
47
* A permutation of all 256 possible bytes.
48
* @type {Array<number>}
49
* @private
50
*/
51
this.state_ = [];
52
53
/**
54
* 8 bit index pointer into this.state_.
55
* @type {number}
56
* @private
57
*/
58
this.index1_ = 0;
59
60
/**
61
* 8 bit index pointer into this.state_.
62
* @type {number}
63
* @private
64
*/
65
this.index2_ = 0;
66
};
67
68
69
/**
70
* Initialize the cipher for use with new key.
71
* @param {Array<number>} key A byte array containing the key.
72
* @param {number=} opt_length Indicates # of bytes to take from the key.
73
*/
74
goog.crypt.Arc4.prototype.setKey = function(key, opt_length) {
75
goog.asserts.assertArray(key, 'Key parameter must be a byte array');
76
77
if (!opt_length) {
78
opt_length = key.length;
79
}
80
81
var state = this.state_;
82
83
for (var i = 0; i < 256; ++i) {
84
state[i] = i;
85
}
86
87
var j = 0;
88
for (var i = 0; i < 256; ++i) {
89
j = (j + state[i] + key[i % opt_length]) & 255;
90
91
var tmp = state[i];
92
state[i] = state[j];
93
state[j] = tmp;
94
}
95
96
this.index1_ = 0;
97
this.index2_ = 0;
98
};
99
100
101
/**
102
* Discards n bytes of the keystream.
103
* These days 1536 is considered a decent amount to drop to get the key state
104
* warmed-up enough for secure usage. This is not done in the constructor to
105
* preserve efficiency for use cases that do not need this.
106
* NOTE: Discard is identical to crypt without actually xoring any data. It's
107
* unfortunate to have this code duplicated, but this was done for performance
108
* reasons. Alternatives which were attempted:
109
* 1. Create a temp array of the correct length and pass it to crypt. This
110
* works but needlessly allocates an array. But more importantly this
111
* requires choosing an array type (Array or Uint8Array) in discard, and
112
* choosing a different type than will be passed to crypt by the client
113
* code hurts the javascript engines ability to optimize crypt (7x hit in
114
* v8).
115
* 2. Make data option in crypt so discard can pass null, this has a huge
116
* perf hit for crypt.
117
* @param {number} length Number of bytes to disregard from the stream.
118
*/
119
goog.crypt.Arc4.prototype.discard = function(length) {
120
var i = this.index1_;
121
var j = this.index2_;
122
var state = this.state_;
123
124
for (var n = 0; n < length; ++n) {
125
i = (i + 1) & 255;
126
j = (j + state[i]) & 255;
127
128
var tmp = state[i];
129
state[i] = state[j];
130
state[j] = tmp;
131
}
132
133
this.index1_ = i;
134
this.index2_ = j;
135
};
136
137
138
/**
139
* En- or decrypt (same operation for streamciphers like ARC4)
140
* @param {Array<number>|Uint8Array} data The data to be xor-ed in place.
141
* @param {number=} opt_length The number of bytes to crypt.
142
*/
143
goog.crypt.Arc4.prototype.crypt = function(data, opt_length) {
144
if (!opt_length) {
145
opt_length = data.length;
146
}
147
var i = this.index1_;
148
var j = this.index2_;
149
var state = this.state_;
150
151
for (var n = 0; n < opt_length; ++n) {
152
i = (i + 1) & 255;
153
j = (j + state[i]) & 255;
154
155
var tmp = state[i];
156
state[i] = state[j];
157
state[j] = tmp;
158
159
data[n] ^= state[(state[i] + state[j]) & 255];
160
}
161
162
this.index1_ = i;
163
this.index2_ = j;
164
};
165
166