-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsig_parser.ts
84 lines (82 loc) · 2.5 KB
/
sig_parser.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import { Sig } from "./sig.ts";
import { Reader } from "./reader.ts";
import { parsePubkey } from "./formats.ts";
import { dearmor } from "./armor.ts";
/**
* Parse bytes into an SSH signature object.
*
* This function throws an Error when the signature is invalid or unsupported.
*
* @param {DataView | string} signature Raw bytes to parse.
*/
export function parse(signature: DataView | string): Sig {
let view;
if (typeof signature === "string") {
const bytes = dearmor(signature);
view = new DataView(bytes.buffer, bytes.byteOffset, bytes.length);
} else {
view = signature;
}
const reader = new Reader(view);
const magic = reader.readBytes(6).toString();
if (magic !== "SSHSIG") {
throw new Error(`Expected SSHSIG magic value but got: ${magic}`);
}
const version = reader.readUint32();
if (version !== 1) {
throw new Error(`Expected version 1 but got: ${version}`);
}
const raw_publickey = reader.peekString().bytes();
const publickey = reader.readString();
const pk_algo = publickey.readString().toString();
const pubkey = parsePubkey(pk_algo, publickey, raw_publickey);
const namespace = reader.readString().toString();
const reserved = reader.readString().bytes();
const hash_algorithm = reader.readString().toString();
const raw_signature = reader.readString();
const sig_algo = raw_signature.readString().toString();
const sig_bytes = raw_signature.readString();
let bytes;
if (
sig_algo === "ecdsa-sha2-nistp256" || sig_algo === "ecdsa-sha2-nistp384" ||
sig_algo === "ecdsa-sha2-nistp512" ||
sig_algo === "[email protected]"
) {
let r = new Uint8Array(sig_bytes.readString().bytes());
if (r[0] === 0x00 && r.length % 2 == 1) {
r = r.slice(1);
}
let s = new Uint8Array(sig_bytes.readString().bytes());
if (s[0] === 0x00 && s.length % 2 == 1) {
s = s.slice(1);
}
bytes = new Uint8Array([...r, ...s]);
} else {
bytes = sig_bytes.bytes();
}
let flags, counter;
if (
sig_algo === "[email protected]" ||
sig_algo == "[email protected]"
) {
flags = new Uint8Array(raw_signature.readBytes(1).bytes())[0];
counter = raw_signature.readUint32();
}
if (!reader.isAtEnd) {
throw new Error(
"Signature was parsed but there were still bytes in the stream.",
);
}
return {
publickey: pubkey,
namespace,
reserved,
hash_algorithm,
signature: {
sig_algo,
raw_signature: bytes,
flags,
counter,
},
};
}