Skip to content

Commit 869f4cf

Browse files
vladski-imb
authored andcommitted
Bug 1881524 - Update ipv6 representation algorithm r=keeler,manuel
Differential Revision: https://phabricator.services.mozilla.com/D265461
1 parent dac43a3 commit 869f4cf

File tree

4 files changed

+118
-13
lines changed

4 files changed

+118
-13
lines changed

toolkit/components/certviewer/content/certDecoder.mjs

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
ECPublicKey,
99
RSAPublicKey,
1010
} from "./vendor/pkijs.js";
11+
import { hexToIpv6Repr, b64ToPEM } from "./components/utils.mjs";
1112

1213
const getTimeZone = () => {
1314
let timeZone = new Date().toString().match(/\(([A-Za-z\s].*)\)/);
@@ -156,14 +157,7 @@ const getSubjectAltNames = (x509, criticalExtensions) => {
156157
];
157158
} else if (address.length === 32) {
158159
// ipv6
159-
return [
160-
strings.san[type],
161-
address
162-
.toLowerCase()
163-
.match(/.{1,4}/g)
164-
.join(":")
165-
.replace(/\b:?(?:0+:?){2,}/, "::"),
166-
];
160+
return [strings.san[type], hexToIpv6Repr(address)];
167161
}
168162
return [strings.san[type], "Unknown IP address"];
169163

@@ -442,11 +436,6 @@ const getMicrosoftCryptographicExtensions = (x509, criticalExtensions) => {
442436
return msCrypto;
443437
};
444438

445-
const b64ToPEM = string => {
446-
let wrapped = string.match(/.{1,64}/g).join("\r\n");
447-
return `-----BEGIN CERTIFICATE-----\r\n${wrapped}\r\n-----END CERTIFICATE-----\r\n`;
448-
};
449-
450439
export const parse = async certificate => {
451440
// certificate could be an array of BER or an array of buffers
452441
const supportedExtensions = [

toolkit/components/certviewer/content/components/utils.mjs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,48 @@ export const b64ToPEM = string => {
2424
let wrapped = string.match(/.{1,64}/g).join("\r\n");
2525
return `-----BEGIN CERTIFICATE-----\r\n${wrapped}\r\n-----END CERTIFICATE-----\r\n`;
2626
};
27+
28+
export const hexToIpv6Repr = ipAddressHex => {
29+
let chunks = ipAddressHex
30+
.match(/.{4}/g)
31+
.map(x => parseInt(x, 16).toString(16));
32+
let longestZeroRunStartIndex = 0;
33+
let longestZeroRunFound = false;
34+
let longestZeroRunLength = 1;
35+
let isCounting = false;
36+
let currentZeroRunLength = 0;
37+
let currentZeroRunStartIndex = 0;
38+
for (let i = 0; i < chunks.length; i++) {
39+
if (chunks[i] == "0" && !isCounting) {
40+
isCounting = true;
41+
currentZeroRunStartIndex = i;
42+
currentZeroRunLength = 1;
43+
} else if (chunks[i] == "0" && isCounting) {
44+
currentZeroRunLength++;
45+
} else if (chunks[i] != "0" && isCounting) {
46+
if (currentZeroRunLength > longestZeroRunLength) {
47+
longestZeroRunLength = currentZeroRunLength;
48+
longestZeroRunFound = true;
49+
longestZeroRunStartIndex = currentZeroRunStartIndex;
50+
currentZeroRunLength = 0;
51+
isCounting = false;
52+
}
53+
}
54+
}
55+
if (isCounting && currentZeroRunLength > longestZeroRunLength) {
56+
longestZeroRunLength = currentZeroRunLength;
57+
longestZeroRunFound = true;
58+
longestZeroRunStartIndex = currentZeroRunStartIndex;
59+
}
60+
if (longestZeroRunFound) {
61+
if (longestZeroRunStartIndex + longestZeroRunLength == chunks.length) {
62+
chunks.push("");
63+
}
64+
if (longestZeroRunStartIndex != 0) {
65+
chunks.splice(longestZeroRunStartIndex, longestZeroRunLength, "");
66+
} else {
67+
chunks.splice(0, longestZeroRunLength, ":");
68+
}
69+
}
70+
return chunks.join(":");
71+
};

toolkit/components/certviewer/tests/chrome/chrome.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,7 @@ support-files = ["parseOutput.mjs"]
99
["test_certDecoderFields.html"]
1010
support-files = ["CSoutput.mjs"]
1111

12+
["test_hexToIpv6Repr.html"]
13+
1214
["test_kebabCaseInAdjustCertInformation.html"]
1315
support-files = ["parseOutput.mjs"]
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>certviewer ipv6 representation test</title>
5+
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
6+
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
7+
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
8+
</head>
9+
<body>
10+
<script type="module">
11+
12+
async function doTest() {
13+
const { hexToIpv6Repr } = await import("chrome://global/content/certviewer/components/utils.mjs");
14+
15+
ok(hexToIpv6Repr, "hexToIpv6Repr should be available in this context");
16+
17+
let tests = [
18+
{
19+
input: "00000000111100000000000000001111",
20+
expected: "0:0:1111::1111"
21+
},
22+
{
23+
input: "262000fe0000000000000000000000fe",
24+
expected: "2620:fe::fe"
25+
},
26+
{
27+
input: "2602ff3a0001abad0c0f0feeabadcafe",
28+
expected: "2602:ff3a:1:abad:c0f:fee:abad:cafe"
29+
},
30+
{
31+
input: "00000000000000000000000000000000",
32+
expected: "::"
33+
},
34+
{
35+
input: "00000000000000000000000000000001",
36+
expected: "::1"
37+
},
38+
{
39+
input: "10000000000000000000000000000000",
40+
expected: "1000::"
41+
},
42+
{
43+
input: "2602ff3a1001abad1c0f1feeabadcafe",
44+
expected: "2602:ff3a:1001:abad:1c0f:1fee:abad:cafe"
45+
},
46+
{
47+
input: "260200001001abad1c0f1feeabadcafe",
48+
expected: "2602:0:1001:abad:1c0f:1fee:abad:cafe"
49+
},
50+
{
51+
input: "00000000000011110000000000001111",
52+
expected: "::1111:0:0:0:1111"
53+
}
54+
];
55+
56+
for (let test of tests) {
57+
let result = hexToIpv6Repr(test.input);
58+
is(result, test.expected, `Ipv6 address incorrectly parsed`);
59+
}
60+
61+
SimpleTest.finish();
62+
}
63+
64+
SimpleTest.waitForExplicitFinish();
65+
doTest();
66+
67+
</script>
68+
</body>
69+
</html>

0 commit comments

Comments
 (0)