susi-qemu 0.0.3 → 0.0.6
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/bin/susi +9 -4
- data/lib/disk.rb +7 -5
- data/lib/novnc/core/base64.js +104 -0
- data/lib/novnc/core/crypto/aes.js +178 -0
- data/lib/novnc/core/crypto/bigint.js +34 -0
- data/lib/novnc/core/crypto/crypto.js +90 -0
- data/lib/novnc/core/crypto/des.js +330 -0
- data/lib/novnc/core/crypto/dh.js +55 -0
- data/lib/novnc/core/crypto/md5.js +82 -0
- data/lib/novnc/core/crypto/rsa.js +132 -0
- data/lib/novnc/core/decoders/copyrect.js +27 -0
- data/lib/novnc/core/decoders/h264.js +321 -0
- data/lib/novnc/core/decoders/hextile.js +181 -0
- data/lib/novnc/core/decoders/jpeg.js +146 -0
- data/lib/novnc/core/decoders/raw.js +59 -0
- data/lib/novnc/core/decoders/rre.js +44 -0
- data/lib/novnc/core/decoders/tight.js +393 -0
- data/lib/novnc/core/decoders/tightpng.js +27 -0
- data/lib/novnc/core/decoders/zlib.js +51 -0
- data/lib/novnc/core/decoders/zrle.js +185 -0
- data/lib/novnc/core/deflator.js +84 -0
- data/lib/novnc/core/display.js +575 -0
- data/lib/novnc/core/encodings.js +53 -0
- data/lib/novnc/core/inflator.js +65 -0
- data/lib/novnc/core/input/domkeytable.js +311 -0
- data/lib/novnc/core/input/fixedkeys.js +129 -0
- data/lib/novnc/core/input/gesturehandler.js +567 -0
- data/lib/novnc/core/input/keyboard.js +294 -0
- data/lib/novnc/core/input/keysym.js +616 -0
- data/lib/novnc/core/input/keysymdef.js +688 -0
- data/lib/novnc/core/input/util.js +191 -0
- data/lib/novnc/core/input/vkeys.js +116 -0
- data/lib/novnc/core/input/xtscancodes.js +173 -0
- data/lib/novnc/core/ra2.js +312 -0
- data/lib/novnc/core/rfb.js +3257 -0
- data/lib/novnc/core/util/browser.js +172 -0
- data/lib/novnc/core/util/cursor.js +249 -0
- data/lib/novnc/core/util/element.js +32 -0
- data/lib/novnc/core/util/events.js +138 -0
- data/lib/novnc/core/util/eventtarget.js +35 -0
- data/lib/novnc/core/util/int.js +15 -0
- data/lib/novnc/core/util/logging.js +56 -0
- data/lib/novnc/core/util/strings.js +28 -0
- data/lib/novnc/core/websock.js +365 -0
- data/lib/novnc/screen.html +21 -0
- data/lib/novnc/vendor/pako/lib/utils/common.js +45 -0
- data/lib/novnc/vendor/pako/lib/zlib/adler32.js +27 -0
- data/lib/novnc/vendor/pako/lib/zlib/constants.js +47 -0
- data/lib/novnc/vendor/pako/lib/zlib/crc32.js +36 -0
- data/lib/novnc/vendor/pako/lib/zlib/deflate.js +1846 -0
- data/lib/novnc/vendor/pako/lib/zlib/gzheader.js +35 -0
- data/lib/novnc/vendor/pako/lib/zlib/inffast.js +324 -0
- data/lib/novnc/vendor/pako/lib/zlib/inflate.js +1527 -0
- data/lib/novnc/vendor/pako/lib/zlib/inftrees.js +322 -0
- data/lib/novnc/vendor/pako/lib/zlib/messages.js +11 -0
- data/lib/novnc/vendor/pako/lib/zlib/trees.js +1195 -0
- data/lib/novnc/vendor/pako/lib/zlib/zstream.js +24 -0
- data/lib/output.rb +11 -0
- data/lib/qmp.rb +6 -0
- data/lib/ssh.rb +3 -1
- data/lib/susi.rb +7 -6
- data/lib/version.rb +1 -1
- data/lib/vm.rb +36 -13
- data/lib/vnc.rb +34 -30
- metadata +85 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4bc88655a9b5207f858886dacd6c466036b42747a3d382d2ea76b2feb0803d82
|
4
|
+
data.tar.gz: 98c59659a0aca9366eab87caef03a5cabcf756b9492905da41bcb6e288b6aec7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3d9101294ba6ac775992dc889c4fe3b39591ddcb78d13665ab7368fcc3f9c7a8abd0a4b9753cae44feb76b204535cdd4df067f42289638835da032935c73e686
|
7
|
+
data.tar.gz: 65716f78fe4b5b4fa5a55aeaef70c7b2e462800d6c0f204c59e866e5ccf15224a42e0af96299e9392ade4d35e223625e05b6abe5e5678a608fd2b012c92a1450
|
data/bin/susi
CHANGED
@@ -57,10 +57,13 @@ elsif ARGV[0] == 'ls'
|
|
57
57
|
Susi::VM.ls
|
58
58
|
|
59
59
|
# open VNC
|
60
|
-
elsif ARGV[0] == 'vnc'
|
61
|
-
|
62
|
-
|
63
|
-
|
60
|
+
elsif ARGV[0] == 'vnc'
|
61
|
+
if ARGV[1].is_a?(String)
|
62
|
+
vm_name = ARGV[1]
|
63
|
+
Susi::VNC.open(vm_name)
|
64
|
+
else
|
65
|
+
Susi::VNC.open(Susi::current_vm_name)
|
66
|
+
end
|
64
67
|
|
65
68
|
# open SSH
|
66
69
|
elsif ARGV[0] == 'ssh'
|
@@ -109,9 +112,11 @@ Usage:
|
|
109
112
|
susi vm ls
|
110
113
|
|
111
114
|
Open VNC
|
115
|
+
susi vnc
|
112
116
|
susi vnc <vm_name>
|
113
117
|
|
114
118
|
Open SSH
|
119
|
+
susi ssh
|
115
120
|
susi ssh <vm_name>
|
116
121
|
|
117
122
|
Download Debian netinstall ISO
|
data/lib/disk.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require_relative 'output'
|
2
|
+
|
1
3
|
module Susi
|
2
4
|
class Disk
|
3
5
|
DEFAULT_IMG = "debian-12.7.0-amd64-netinst.iso"
|
@@ -16,7 +18,7 @@ module Susi
|
|
16
18
|
|
17
19
|
url = "https://mirrors.tuna.tsinghua.edu.cn/debian-cd/current/amd64/iso-cd/#{DEFAULT_IMG}"
|
18
20
|
|
19
|
-
|
21
|
+
Susi::debug "Downloading Debian netinstall ISO..."
|
20
22
|
|
21
23
|
begin
|
22
24
|
URI.open(url) do |remote_file|
|
@@ -24,13 +26,13 @@ module Susi
|
|
24
26
|
local_file.write(remote_file.read)
|
25
27
|
end
|
26
28
|
end
|
27
|
-
|
29
|
+
Susi::debug "Download completed successfully."
|
28
30
|
rescue OpenURI::HTTPError => e
|
29
|
-
|
31
|
+
Susi::debug "Error downloading the ISO: #{e.message}"
|
30
32
|
rescue SocketError => e
|
31
|
-
|
33
|
+
Susi::debug "Network error: #{e.message}"
|
32
34
|
rescue => e
|
33
|
-
|
35
|
+
Susi::debug "An unexpected error occurred: #{e.message}"
|
34
36
|
end
|
35
37
|
end
|
36
38
|
|
@@ -0,0 +1,104 @@
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
3
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
4
|
+
|
5
|
+
// From: http://hg.mozilla.org/mozilla-central/raw-file/ec10630b1a54/js/src/devtools/jint/sunspider/string-base64.js
|
6
|
+
|
7
|
+
import * as Log from './util/logging.js';
|
8
|
+
|
9
|
+
export default {
|
10
|
+
/* Convert data (an array of integers) to a Base64 string. */
|
11
|
+
toBase64Table: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split(''),
|
12
|
+
base64Pad: '=',
|
13
|
+
|
14
|
+
encode(data) {
|
15
|
+
"use strict";
|
16
|
+
let result = '';
|
17
|
+
const length = data.length;
|
18
|
+
const lengthpad = (length % 3);
|
19
|
+
// Convert every three bytes to 4 ascii characters.
|
20
|
+
|
21
|
+
for (let i = 0; i < (length - 2); i += 3) {
|
22
|
+
result += this.toBase64Table[data[i] >> 2];
|
23
|
+
result += this.toBase64Table[((data[i] & 0x03) << 4) + (data[i + 1] >> 4)];
|
24
|
+
result += this.toBase64Table[((data[i + 1] & 0x0f) << 2) + (data[i + 2] >> 6)];
|
25
|
+
result += this.toBase64Table[data[i + 2] & 0x3f];
|
26
|
+
}
|
27
|
+
|
28
|
+
// Convert the remaining 1 or 2 bytes, pad out to 4 characters.
|
29
|
+
const j = length - lengthpad;
|
30
|
+
if (lengthpad === 2) {
|
31
|
+
result += this.toBase64Table[data[j] >> 2];
|
32
|
+
result += this.toBase64Table[((data[j] & 0x03) << 4) + (data[j + 1] >> 4)];
|
33
|
+
result += this.toBase64Table[(data[j + 1] & 0x0f) << 2];
|
34
|
+
result += this.toBase64Table[64];
|
35
|
+
} else if (lengthpad === 1) {
|
36
|
+
result += this.toBase64Table[data[j] >> 2];
|
37
|
+
result += this.toBase64Table[(data[j] & 0x03) << 4];
|
38
|
+
result += this.toBase64Table[64];
|
39
|
+
result += this.toBase64Table[64];
|
40
|
+
}
|
41
|
+
|
42
|
+
return result;
|
43
|
+
},
|
44
|
+
|
45
|
+
/* Convert Base64 data to a string */
|
46
|
+
/* eslint-disable comma-spacing */
|
47
|
+
toBinaryTable: [
|
48
|
+
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
49
|
+
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
50
|
+
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
|
51
|
+
52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1,
|
52
|
+
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
|
53
|
+
15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
|
54
|
+
-1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
|
55
|
+
41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
|
56
|
+
],
|
57
|
+
/* eslint-enable comma-spacing */
|
58
|
+
|
59
|
+
decode(data, offset = 0) {
|
60
|
+
let dataLength = data.indexOf('=') - offset;
|
61
|
+
if (dataLength < 0) { dataLength = data.length - offset; }
|
62
|
+
|
63
|
+
/* Every four characters is 3 resulting numbers */
|
64
|
+
const resultLength = (dataLength >> 2) * 3 + Math.floor((dataLength % 4) / 1.5);
|
65
|
+
const result = new Array(resultLength);
|
66
|
+
|
67
|
+
// Convert one by one.
|
68
|
+
|
69
|
+
let leftbits = 0; // number of bits decoded, but yet to be appended
|
70
|
+
let leftdata = 0; // bits decoded, but yet to be appended
|
71
|
+
for (let idx = 0, i = offset; i < data.length; i++) {
|
72
|
+
const c = this.toBinaryTable[data.charCodeAt(i) & 0x7f];
|
73
|
+
const padding = (data.charAt(i) === this.base64Pad);
|
74
|
+
// Skip illegal characters and whitespace
|
75
|
+
if (c === -1) {
|
76
|
+
Log.Error("Illegal character code " + data.charCodeAt(i) + " at position " + i);
|
77
|
+
continue;
|
78
|
+
}
|
79
|
+
|
80
|
+
// Collect data into leftdata, update bitcount
|
81
|
+
leftdata = (leftdata << 6) | c;
|
82
|
+
leftbits += 6;
|
83
|
+
|
84
|
+
// If we have 8 or more bits, append 8 bits to the result
|
85
|
+
if (leftbits >= 8) {
|
86
|
+
leftbits -= 8;
|
87
|
+
// Append if not padding.
|
88
|
+
if (!padding) {
|
89
|
+
result[idx++] = (leftdata >> leftbits) & 0xff;
|
90
|
+
}
|
91
|
+
leftdata &= (1 << leftbits) - 1;
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
// If there are any bits left, the base64 string was corrupted
|
96
|
+
if (leftbits) {
|
97
|
+
const err = new Error('Corrupted base64 string');
|
98
|
+
err.name = 'Base64-Error';
|
99
|
+
throw err;
|
100
|
+
}
|
101
|
+
|
102
|
+
return result;
|
103
|
+
}
|
104
|
+
}; /* End of Base64 namespace */
|
@@ -0,0 +1,178 @@
|
|
1
|
+
export class AESECBCipher {
|
2
|
+
constructor() {
|
3
|
+
this._key = null;
|
4
|
+
}
|
5
|
+
|
6
|
+
get algorithm() {
|
7
|
+
return { name: "AES-ECB" };
|
8
|
+
}
|
9
|
+
|
10
|
+
static async importKey(key, _algorithm, extractable, keyUsages) {
|
11
|
+
const cipher = new AESECBCipher;
|
12
|
+
await cipher._importKey(key, extractable, keyUsages);
|
13
|
+
return cipher;
|
14
|
+
}
|
15
|
+
|
16
|
+
async _importKey(key, extractable, keyUsages) {
|
17
|
+
this._key = await window.crypto.subtle.importKey(
|
18
|
+
"raw", key, {name: "AES-CBC"}, extractable, keyUsages);
|
19
|
+
}
|
20
|
+
|
21
|
+
async encrypt(_algorithm, plaintext) {
|
22
|
+
const x = new Uint8Array(plaintext);
|
23
|
+
if (x.length % 16 !== 0 || this._key === null) {
|
24
|
+
return null;
|
25
|
+
}
|
26
|
+
const n = x.length / 16;
|
27
|
+
for (let i = 0; i < n; i++) {
|
28
|
+
const y = new Uint8Array(await window.crypto.subtle.encrypt({
|
29
|
+
name: "AES-CBC",
|
30
|
+
iv: new Uint8Array(16),
|
31
|
+
}, this._key, x.slice(i * 16, i * 16 + 16))).slice(0, 16);
|
32
|
+
x.set(y, i * 16);
|
33
|
+
}
|
34
|
+
return x;
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
export class AESEAXCipher {
|
39
|
+
constructor() {
|
40
|
+
this._rawKey = null;
|
41
|
+
this._ctrKey = null;
|
42
|
+
this._cbcKey = null;
|
43
|
+
this._zeroBlock = new Uint8Array(16);
|
44
|
+
this._prefixBlock0 = this._zeroBlock;
|
45
|
+
this._prefixBlock1 = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
|
46
|
+
this._prefixBlock2 = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]);
|
47
|
+
}
|
48
|
+
|
49
|
+
get algorithm() {
|
50
|
+
return { name: "AES-EAX" };
|
51
|
+
}
|
52
|
+
|
53
|
+
async _encryptBlock(block) {
|
54
|
+
const encrypted = await window.crypto.subtle.encrypt({
|
55
|
+
name: "AES-CBC",
|
56
|
+
iv: this._zeroBlock,
|
57
|
+
}, this._cbcKey, block);
|
58
|
+
return new Uint8Array(encrypted).slice(0, 16);
|
59
|
+
}
|
60
|
+
|
61
|
+
async _initCMAC() {
|
62
|
+
const k1 = await this._encryptBlock(this._zeroBlock);
|
63
|
+
const k2 = new Uint8Array(16);
|
64
|
+
const v = k1[0] >>> 6;
|
65
|
+
for (let i = 0; i < 15; i++) {
|
66
|
+
k2[i] = (k1[i + 1] >> 6) | (k1[i] << 2);
|
67
|
+
k1[i] = (k1[i + 1] >> 7) | (k1[i] << 1);
|
68
|
+
}
|
69
|
+
const lut = [0x0, 0x87, 0x0e, 0x89];
|
70
|
+
k2[14] ^= v >>> 1;
|
71
|
+
k2[15] = (k1[15] << 2) ^ lut[v];
|
72
|
+
k1[15] = (k1[15] << 1) ^ lut[v >> 1];
|
73
|
+
this._k1 = k1;
|
74
|
+
this._k2 = k2;
|
75
|
+
}
|
76
|
+
|
77
|
+
async _encryptCTR(data, counter) {
|
78
|
+
const encrypted = await window.crypto.subtle.encrypt({
|
79
|
+
name: "AES-CTR",
|
80
|
+
counter: counter,
|
81
|
+
length: 128
|
82
|
+
}, this._ctrKey, data);
|
83
|
+
return new Uint8Array(encrypted);
|
84
|
+
}
|
85
|
+
|
86
|
+
async _decryptCTR(data, counter) {
|
87
|
+
const decrypted = await window.crypto.subtle.decrypt({
|
88
|
+
name: "AES-CTR",
|
89
|
+
counter: counter,
|
90
|
+
length: 128
|
91
|
+
}, this._ctrKey, data);
|
92
|
+
return new Uint8Array(decrypted);
|
93
|
+
}
|
94
|
+
|
95
|
+
async _computeCMAC(data, prefixBlock) {
|
96
|
+
if (prefixBlock.length !== 16) {
|
97
|
+
return null;
|
98
|
+
}
|
99
|
+
const n = Math.floor(data.length / 16);
|
100
|
+
const m = Math.ceil(data.length / 16);
|
101
|
+
const r = data.length - n * 16;
|
102
|
+
const cbcData = new Uint8Array((m + 1) * 16);
|
103
|
+
cbcData.set(prefixBlock);
|
104
|
+
cbcData.set(data, 16);
|
105
|
+
if (r === 0) {
|
106
|
+
for (let i = 0; i < 16; i++) {
|
107
|
+
cbcData[n * 16 + i] ^= this._k1[i];
|
108
|
+
}
|
109
|
+
} else {
|
110
|
+
cbcData[(n + 1) * 16 + r] = 0x80;
|
111
|
+
for (let i = 0; i < 16; i++) {
|
112
|
+
cbcData[(n + 1) * 16 + i] ^= this._k2[i];
|
113
|
+
}
|
114
|
+
}
|
115
|
+
let cbcEncrypted = await window.crypto.subtle.encrypt({
|
116
|
+
name: "AES-CBC",
|
117
|
+
iv: this._zeroBlock,
|
118
|
+
}, this._cbcKey, cbcData);
|
119
|
+
|
120
|
+
cbcEncrypted = new Uint8Array(cbcEncrypted);
|
121
|
+
const mac = cbcEncrypted.slice(cbcEncrypted.length - 32, cbcEncrypted.length - 16);
|
122
|
+
return mac;
|
123
|
+
}
|
124
|
+
|
125
|
+
static async importKey(key, _algorithm, _extractable, _keyUsages) {
|
126
|
+
const cipher = new AESEAXCipher;
|
127
|
+
await cipher._importKey(key);
|
128
|
+
return cipher;
|
129
|
+
}
|
130
|
+
|
131
|
+
async _importKey(key) {
|
132
|
+
this._rawKey = key;
|
133
|
+
this._ctrKey = await window.crypto.subtle.importKey(
|
134
|
+
"raw", key, {name: "AES-CTR"}, false, ["encrypt", "decrypt"]);
|
135
|
+
this._cbcKey = await window.crypto.subtle.importKey(
|
136
|
+
"raw", key, {name: "AES-CBC"}, false, ["encrypt"]);
|
137
|
+
await this._initCMAC();
|
138
|
+
}
|
139
|
+
|
140
|
+
async encrypt(algorithm, message) {
|
141
|
+
const ad = algorithm.additionalData;
|
142
|
+
const nonce = algorithm.iv;
|
143
|
+
const nCMAC = await this._computeCMAC(nonce, this._prefixBlock0);
|
144
|
+
const encrypted = await this._encryptCTR(message, nCMAC);
|
145
|
+
const adCMAC = await this._computeCMAC(ad, this._prefixBlock1);
|
146
|
+
const mac = await this._computeCMAC(encrypted, this._prefixBlock2);
|
147
|
+
for (let i = 0; i < 16; i++) {
|
148
|
+
mac[i] ^= nCMAC[i] ^ adCMAC[i];
|
149
|
+
}
|
150
|
+
const res = new Uint8Array(16 + encrypted.length);
|
151
|
+
res.set(encrypted);
|
152
|
+
res.set(mac, encrypted.length);
|
153
|
+
return res;
|
154
|
+
}
|
155
|
+
|
156
|
+
async decrypt(algorithm, data) {
|
157
|
+
const encrypted = data.slice(0, data.length - 16);
|
158
|
+
const ad = algorithm.additionalData;
|
159
|
+
const nonce = algorithm.iv;
|
160
|
+
const mac = data.slice(data.length - 16);
|
161
|
+
const nCMAC = await this._computeCMAC(nonce, this._prefixBlock0);
|
162
|
+
const adCMAC = await this._computeCMAC(ad, this._prefixBlock1);
|
163
|
+
const computedMac = await this._computeCMAC(encrypted, this._prefixBlock2);
|
164
|
+
for (let i = 0; i < 16; i++) {
|
165
|
+
computedMac[i] ^= nCMAC[i] ^ adCMAC[i];
|
166
|
+
}
|
167
|
+
if (computedMac.length !== mac.length) {
|
168
|
+
return null;
|
169
|
+
}
|
170
|
+
for (let i = 0; i < mac.length; i++) {
|
171
|
+
if (computedMac[i] !== mac[i]) {
|
172
|
+
return null;
|
173
|
+
}
|
174
|
+
}
|
175
|
+
const res = await this._decryptCTR(encrypted, nCMAC);
|
176
|
+
return res;
|
177
|
+
}
|
178
|
+
}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
export function modPow(b, e, m) {
|
2
|
+
let r = 1n;
|
3
|
+
b = b % m;
|
4
|
+
while (e > 0n) {
|
5
|
+
if ((e & 1n) === 1n) {
|
6
|
+
r = (r * b) % m;
|
7
|
+
}
|
8
|
+
e = e >> 1n;
|
9
|
+
b = (b * b) % m;
|
10
|
+
}
|
11
|
+
return r;
|
12
|
+
}
|
13
|
+
|
14
|
+
export function bigIntToU8Array(bigint, padLength=0) {
|
15
|
+
let hex = bigint.toString(16);
|
16
|
+
if (padLength === 0) {
|
17
|
+
padLength = Math.ceil(hex.length / 2);
|
18
|
+
}
|
19
|
+
hex = hex.padStart(padLength * 2, '0');
|
20
|
+
const length = hex.length / 2;
|
21
|
+
const arr = new Uint8Array(length);
|
22
|
+
for (let i = 0; i < length; i++) {
|
23
|
+
arr[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
24
|
+
}
|
25
|
+
return arr;
|
26
|
+
}
|
27
|
+
|
28
|
+
export function u8ArrayToBigInt(arr) {
|
29
|
+
let hex = '0x';
|
30
|
+
for (let i = 0; i < arr.length; i++) {
|
31
|
+
hex += arr[i].toString(16).padStart(2, '0');
|
32
|
+
}
|
33
|
+
return BigInt(hex);
|
34
|
+
}
|
@@ -0,0 +1,90 @@
|
|
1
|
+
import { AESECBCipher, AESEAXCipher } from "./aes.js";
|
2
|
+
import { DESCBCCipher, DESECBCipher } from "./des.js";
|
3
|
+
import { RSACipher } from "./rsa.js";
|
4
|
+
import { DHCipher } from "./dh.js";
|
5
|
+
import { MD5 } from "./md5.js";
|
6
|
+
|
7
|
+
// A single interface for the cryptographic algorithms not supported by SubtleCrypto.
|
8
|
+
// Both synchronous and asynchronous implmentations are allowed.
|
9
|
+
class LegacyCrypto {
|
10
|
+
constructor() {
|
11
|
+
this._algorithms = {
|
12
|
+
"AES-ECB": AESECBCipher,
|
13
|
+
"AES-EAX": AESEAXCipher,
|
14
|
+
"DES-ECB": DESECBCipher,
|
15
|
+
"DES-CBC": DESCBCCipher,
|
16
|
+
"RSA-PKCS1-v1_5": RSACipher,
|
17
|
+
"DH": DHCipher,
|
18
|
+
"MD5": MD5,
|
19
|
+
};
|
20
|
+
}
|
21
|
+
|
22
|
+
encrypt(algorithm, key, data) {
|
23
|
+
if (key.algorithm.name !== algorithm.name) {
|
24
|
+
throw new Error("algorithm does not match");
|
25
|
+
}
|
26
|
+
if (typeof key.encrypt !== "function") {
|
27
|
+
throw new Error("key does not support encryption");
|
28
|
+
}
|
29
|
+
return key.encrypt(algorithm, data);
|
30
|
+
}
|
31
|
+
|
32
|
+
decrypt(algorithm, key, data) {
|
33
|
+
if (key.algorithm.name !== algorithm.name) {
|
34
|
+
throw new Error("algorithm does not match");
|
35
|
+
}
|
36
|
+
if (typeof key.decrypt !== "function") {
|
37
|
+
throw new Error("key does not support encryption");
|
38
|
+
}
|
39
|
+
return key.decrypt(algorithm, data);
|
40
|
+
}
|
41
|
+
|
42
|
+
importKey(format, keyData, algorithm, extractable, keyUsages) {
|
43
|
+
if (format !== "raw") {
|
44
|
+
throw new Error("key format is not supported");
|
45
|
+
}
|
46
|
+
const alg = this._algorithms[algorithm.name];
|
47
|
+
if (typeof alg === "undefined" || typeof alg.importKey !== "function") {
|
48
|
+
throw new Error("algorithm is not supported");
|
49
|
+
}
|
50
|
+
return alg.importKey(keyData, algorithm, extractable, keyUsages);
|
51
|
+
}
|
52
|
+
|
53
|
+
generateKey(algorithm, extractable, keyUsages) {
|
54
|
+
const alg = this._algorithms[algorithm.name];
|
55
|
+
if (typeof alg === "undefined" || typeof alg.generateKey !== "function") {
|
56
|
+
throw new Error("algorithm is not supported");
|
57
|
+
}
|
58
|
+
return alg.generateKey(algorithm, extractable, keyUsages);
|
59
|
+
}
|
60
|
+
|
61
|
+
exportKey(format, key) {
|
62
|
+
if (format !== "raw") {
|
63
|
+
throw new Error("key format is not supported");
|
64
|
+
}
|
65
|
+
if (typeof key.exportKey !== "function") {
|
66
|
+
throw new Error("key does not support exportKey");
|
67
|
+
}
|
68
|
+
return key.exportKey();
|
69
|
+
}
|
70
|
+
|
71
|
+
digest(algorithm, data) {
|
72
|
+
const alg = this._algorithms[algorithm];
|
73
|
+
if (typeof alg !== "function") {
|
74
|
+
throw new Error("algorithm is not supported");
|
75
|
+
}
|
76
|
+
return alg(data);
|
77
|
+
}
|
78
|
+
|
79
|
+
deriveBits(algorithm, key, length) {
|
80
|
+
if (key.algorithm.name !== algorithm.name) {
|
81
|
+
throw new Error("algorithm does not match");
|
82
|
+
}
|
83
|
+
if (typeof key.deriveBits !== "function") {
|
84
|
+
throw new Error("key does not support deriveBits");
|
85
|
+
}
|
86
|
+
return key.deriveBits(algorithm, length);
|
87
|
+
}
|
88
|
+
}
|
89
|
+
|
90
|
+
export default new LegacyCrypto;
|