mirror of
https://github.com/oxen-io/session-desktop.git
synced 2023-12-14 02:12:57 +01:00
Merge pull request #1566 from Bilb/certificate-pinning
pin certificates for seed nodes
This commit is contained in:
commit
01b5591c04
7 changed files with 185 additions and 14 deletions
24
certificates/public-loki-foundation.crt
Normal file
24
certificates/public-loki-foundation.crt
Normal file
|
@ -0,0 +1,24 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEEzCCAvugAwIBAgIUY9RQqbjhsQEkdeSgV9L0os9xZ7AwDQYJKoZIhvcNAQEL
|
||||
BQAwfDELMAkGA1UEBhMCQVUxETAPBgNVBAgMCFZpY3RvcmlhMRIwEAYDVQQHDAlN
|
||||
ZWxib3VybmUxJTAjBgNVBAoMHE94ZW4gUHJpdmFjeSBUZWNoIEZvdW5kYXRpb24x
|
||||
HzAdBgNVBAMMFnB1YmxpYy5sb2tpLmZvdW5kYXRpb24wHhcNMjEwNDA3MDExMDMx
|
||||
WhcNMjMwNDA3MDExMDMxWjB8MQswCQYDVQQGEwJBVTERMA8GA1UECAwIVmljdG9y
|
||||
aWExEjAQBgNVBAcMCU1lbGJvdXJuZTElMCMGA1UECgwcT3hlbiBQcml2YWN5IFRl
|
||||
Y2ggRm91bmRhdGlvbjEfMB0GA1UEAwwWcHVibGljLmxva2kuZm91bmRhdGlvbjCC
|
||||
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM5dBJSIR5+VNNUxUOo6FG0e
|
||||
RmZteRqBt50KXGbOi2A23a6sa57pLFh9Yw3hmlWV+QCL7ipG1X4IC55OStgoesf+
|
||||
K65VwEMP6Mtq0sSJS3R5TiuV2ZSRdSZTVjUyRXVe5T4Aw6wXVTAbc/HsyS780tDh
|
||||
GclfDHhonPhZpmTAnSbfMOS+BfOnBNvDxdto0kVh6k5nrGlkT4ECloulHTQF2lwJ
|
||||
0D6IOtv9AJplPdg6s2c4dY7durOdvr3NNVfvn5PTeRvbEPqzZur4WUUKIPNGu6mY
|
||||
PxImqd4eUsL0Vod4aAsTIx4YMmCTi0m9W6zJI6nXcK/6a+iiA3+NTNMzEA9gQhEC
|
||||
AwEAAaOBjDCBiTAdBgNVHQ4EFgQU/zahokxLvvFUpbnM6z/pwS1KsvwwHwYDVR0j
|
||||
BBgwFoAU/zahokxLvvFUpbnM6z/pwS1KsvwwDwYDVR0TAQH/BAUwAwEB/zAhBgNV
|
||||
HREEGjAYghZwdWJsaWMubG9raS5mb3VuZGF0aW9uMBMGA1UdJQQMMAoGCCsGAQUF
|
||||
BwMBMA0GCSqGSIb3DQEBCwUAA4IBAQBql+JvoqpaYrFFTOuDn08U+pdcd3GM7tbI
|
||||
zRH5LU+YnIpp9aRheek+2COW8DXsIy/kUngETCMLmX6ZaUj/WdHnTDkB0KTgxSHv
|
||||
ad3ZznKPKZ26qJOklr+0ZWj4J3jHbisSzql6mqq7R2Kp4ESwzwqxvkbykM5RUnmz
|
||||
Go/3Ol7bpN/ZVwwEkGfD/5rRHf57E/gZn2pBO+zotlQgr7HKRsIXQ2hIXVQqWmPQ
|
||||
lvfIwrwAZlfES7BARFnHOpyVQxV8uNcV5K5eXzuVFjHBqvq+BtyGhWkP9yKJCHS9
|
||||
OUXxch0rzRsH2C/kRVVhEk0pI3qlFiRC8pCJs98SNE9l69EQtG7I
|
||||
-----END CERTIFICATE-----
|
25
certificates/storage-seed-1.crt
Normal file
25
certificates/storage-seed-1.crt
Normal file
|
@ -0,0 +1,25 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEITCCAwmgAwIBAgIUJsox1ZQPK/6iDsCC+MUJfNAlFuYwDQYJKoZIhvcNAQEL
|
||||
BQAwgYAxCzAJBgNVBAYTAkFVMREwDwYDVQQIDAhWaWN0b3JpYTESMBAGA1UEBwwJ
|
||||
TWVsYm91cm5lMSUwIwYDVQQKDBxPeGVuIFByaXZhY3kgVGVjaCBGb3VuZGF0aW9u
|
||||
MSMwIQYDVQQDDBpzdG9yYWdlLnNlZWQxLmxva2kubmV0d29yazAeFw0yMTA0MDcw
|
||||
MTE5MjZaFw0yMzA0MDcwMTE5MjZaMIGAMQswCQYDVQQGEwJBVTERMA8GA1UECAwI
|
||||
VmljdG9yaWExEjAQBgNVBAcMCU1lbGJvdXJuZTElMCMGA1UECgwcT3hlbiBQcml2
|
||||
YWN5IFRlY2ggRm91bmRhdGlvbjEjMCEGA1UEAwwac3RvcmFnZS5zZWVkMS5sb2tp
|
||||
Lm5ldHdvcmswggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtWH3Rz8Dd
|
||||
kEmM7tcBWHrJ/G8drr/+qidboEVYzxpyRjszaDxKXVhx4eBBsAD5RuCWuTuZmM8k
|
||||
TKEDLtf8xfb5SQ7YNX+346s9NXS5Poy4CIPASiW/QWXgIHFbVdv2hC+cKOP61OLM
|
||||
OGnOxfig6tQyd6EaCkedpY1DvSa2lPnQSOwC/jXCx6Vboc0zTY5R2bHtNc9hjIFP
|
||||
F4VClLAQSh2F4R1V9MH5KZMW+CCP6oaJY658W9JYXYRwlLrL2EFOVxHgcxq/6+fw
|
||||
+axXK9OXJrGZjuA+hiz+L/uAOtE4WuxrSeuNMHSrMtM9QqVn4bBuMJ21mAzfNoMP
|
||||
OIwgMT9DwUjVAgMBAAGjgZAwgY0wHQYDVR0OBBYEFOubJp9SoXIw+ONiWgkOaW8K
|
||||
zI/TMB8GA1UdIwQYMBaAFOubJp9SoXIw+ONiWgkOaW8KzI/TMA8GA1UdEwEB/wQF
|
||||
MAMBAf8wJQYDVR0RBB4wHIIac3RvcmFnZS5zZWVkMS5sb2tpLm5ldHdvcmswEwYD
|
||||
VR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAIiHNhNrjYvwXVWs
|
||||
gacx8T/dpqpu9GE3L17LotgQr4R+IYHpNtcmwOTdtWWFfUTr75OCs+c3DqgRKEoj
|
||||
lnULOsVcalpAGIvW15/fmZWOf66Dpa4+ljDmAc3SOQiD0gGNtqblgI5zG1HF38QP
|
||||
hjYRhCZ5CVeGOLucvQ8tVVwQvArPFIkBr0jH9jHVgRWEI2MeI3FsU2H93D4TfGln
|
||||
N4SmmCfYBqygaaZBWkJEt0bYhn8uGHdU9UY9L2FPtfHVKkmFgO7cASGlvXS7B/TT
|
||||
/8IgbtM3O8mZc2asmdQhGwoAKz93ryyCd8X2UZJg/IwCSCayOlYZWY2fR4OPQmmV
|
||||
gxJsm+g=
|
||||
-----END CERTIFICATE-----
|
25
certificates/storage-seed-3.crt
Normal file
25
certificates/storage-seed-3.crt
Normal file
|
@ -0,0 +1,25 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEITCCAwmgAwIBAgIUc486Dy9Y00bUFfDeYmJIgSS5xREwDQYJKoZIhvcNAQEL
|
||||
BQAwgYAxCzAJBgNVBAYTAkFVMREwDwYDVQQIDAhWaWN0b3JpYTESMBAGA1UEBwwJ
|
||||
TWVsYm91cm5lMSUwIwYDVQQKDBxPeGVuIFByaXZhY3kgVGVjaCBGb3VuZGF0aW9u
|
||||
MSMwIQYDVQQDDBpzdG9yYWdlLnNlZWQzLmxva2kubmV0d29yazAeFw0yMTA0MDcw
|
||||
MTIwNTJaFw0yMzA0MDcwMTIwNTJaMIGAMQswCQYDVQQGEwJBVTERMA8GA1UECAwI
|
||||
VmljdG9yaWExEjAQBgNVBAcMCU1lbGJvdXJuZTElMCMGA1UECgwcT3hlbiBQcml2
|
||||
YWN5IFRlY2ggRm91bmRhdGlvbjEjMCEGA1UEAwwac3RvcmFnZS5zZWVkMy5sb2tp
|
||||
Lm5ldHdvcmswggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtokMlsFzf
|
||||
piYeD0EVNikMyvjltpF6fUEde9NOVrTtNTQT6kkDk+/0HF5LYgPaatv6v7fpUQHi
|
||||
kIwd6F0LTRGeWDFdsaWMdtlR1n/GxLPrOROsE8dcLt6GLavPf9rDabgva93m/JD6
|
||||
XW+Ne+MPEwqS8dAmFGhZd0gju6AtKFoSHnIf5pSQN6fSZUF/JQtHLVprAKKWKDiS
|
||||
ZwmWbmrZR2aofLD/VRpetabajnZlv9EeWloQwvUsw1C1hkAmmtFeeXtg7ePwrOzo
|
||||
6CnmcUJwOmi+LWqQV4A+58RZPFKaZoC5pzaKd0OYB8eZ8HB1F41UjGJgheX5Cyl4
|
||||
+amfF3l8dSq1AgMBAAGjgZAwgY0wHQYDVR0OBBYEFM9VSq4pGydjtX92Beul4+ml
|
||||
jBKtMB8GA1UdIwQYMBaAFM9VSq4pGydjtX92Beul4+mljBKtMA8GA1UdEwEB/wQF
|
||||
MAMBAf8wJQYDVR0RBB4wHIIac3RvcmFnZS5zZWVkMy5sb2tpLm5ldHdvcmswEwYD
|
||||
VR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAAYxmhhkcKE1n6g1
|
||||
JqOa3UCBo4EfbqY5+FDZ0FVqv/cwemwVpKLbe6luRIS8poomdPCyMOS45V7wN3H9
|
||||
cFpfJ1TW19ydPVKmCXrl29ngmnY1q7YDwE/4qi3VK/UiqDkTHMKWjVPkenOyi8u6
|
||||
VVQANXSnKrn6GtigNFjGyD38O+j7AUSXBtXOJczaoF6r6BWgwQZ2WmgjuwvKTWSN
|
||||
4r8uObERoAQYVaeXfgdr4e9X/JdskBDaLFfoW/rrSozHB4FqVNFW96k+aIUgRa5p
|
||||
9kv115QcBPCSh9qOyTHij4tswS6SyOFaiKrNC4hgHQXP4QgioKmtsR/2Y+qJ6ddH
|
||||
6oo+4QU=
|
||||
-----END CERTIFICATE-----
|
|
@ -6,16 +6,16 @@
|
|||
"defaultPoWDifficulty": "1",
|
||||
"seedNodeList": [
|
||||
{
|
||||
"ip_url": "http://116.203.53.213/",
|
||||
"url": "https://storage.seed1.loki.network/"
|
||||
"ip_url": "http://116.203.53.213:4433/",
|
||||
"url": "https://storage.seed1.loki.network:4433/"
|
||||
},
|
||||
{
|
||||
"ip_url": "http://212.199.114.66/",
|
||||
"url": "https://storage.seed3.loki.network/"
|
||||
"ip_url": "http://212.199.114.66:4433/",
|
||||
"url": "https://storage.seed3.loki.network:4433/"
|
||||
},
|
||||
{
|
||||
"ip_url": "http://144.76.164.202/",
|
||||
"url": "https://public.loki.foundation/"
|
||||
"ip_url": "http://144.76.164.202:4433/",
|
||||
"url": "https://public.loki.foundation:4433/"
|
||||
}
|
||||
],
|
||||
"updatesEnabled": false,
|
||||
|
|
|
@ -304,6 +304,7 @@
|
|||
"debug_log_preload.js",
|
||||
"password_preload.js",
|
||||
"main.js",
|
||||
"certificates/**",
|
||||
"images/**",
|
||||
"fonts/*",
|
||||
"build/assets",
|
||||
|
|
|
@ -1,5 +1,14 @@
|
|||
// we don't throw or catch here
|
||||
import { default as insecureNodeFetch } from 'node-fetch';
|
||||
import https from 'https';
|
||||
import crypto from 'crypto';
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import tls from 'tls';
|
||||
import Electron from 'electron';
|
||||
|
||||
const { remote } = Electron;
|
||||
|
||||
import { snodeRpc } from './lokiRpc';
|
||||
import {
|
||||
|
@ -78,6 +87,93 @@ export async function getVersion(
|
|||
}
|
||||
}
|
||||
|
||||
const sha256 = (s: string) => {
|
||||
return crypto
|
||||
.createHash('sha256')
|
||||
.update(s)
|
||||
.digest('base64');
|
||||
};
|
||||
|
||||
const getSslAgentForSeedNode = (seedNodeHost: string) => {
|
||||
let filePrefix = '';
|
||||
let pubkey256 = '';
|
||||
let cert256 = '';
|
||||
|
||||
switch (seedNodeHost) {
|
||||
case 'storage.seed1.loki.network':
|
||||
filePrefix = 'storage-seed-1';
|
||||
pubkey256 = 'JOsnIcAanVbgECNA8lHtC8f/cqN9m8EP7jKT6XCjeL8=';
|
||||
cert256 =
|
||||
'6E:2B:AC:F3:6E:C1:FF:FF:24:F3:CA:92:C6:94:81:B4:82:43:DF:C7:C6:03:98:B8:F5:6B:7D:30:7B:16:C1:CB';
|
||||
break;
|
||||
case 'storage.seed3.loki.network':
|
||||
filePrefix = 'storage-seed-3';
|
||||
pubkey256 = 'mMmZD3lG4Fi7nTC/EWzRVaU3bbCLsH6Ds2FHSTpo0Rk=';
|
||||
cert256 =
|
||||
'24:13:4C:0A:03:D8:42:A6:09:DE:35:76:F4:BD:FB:11:60:DB:F9:88:9F:98:46:B7:60:A6:60:0C:4C:CF:60:72';
|
||||
|
||||
break;
|
||||
case 'public.loki.foundation':
|
||||
filePrefix = 'public-loki-foundation';
|
||||
pubkey256 = 'W+Zv52qlcm1BbdpJzFwxZrE7kfmEboq7h3Dp/+Q3RPg=';
|
||||
cert256 =
|
||||
'40:E4:67:7D:18:6B:4D:08:8D:E9:D5:47:52:25:B8:28:E0:D3:63:99:9B:38:46:7D:92:19:5B:61:B9:AE:0E:EA';
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown seed node: ${seedNodeHost}`);
|
||||
}
|
||||
// tslint:disable: non-literal-fs-path
|
||||
// read the cert each time. We only run this request once for each seed node nevertheless.
|
||||
const appPath = remote.app.getAppPath();
|
||||
const crt = fs.readFileSync(
|
||||
path.join(appPath, `/certificates/${filePrefix}.crt`),
|
||||
'utf-8'
|
||||
);
|
||||
// debugger;
|
||||
const sslOptions = {
|
||||
// as the seed nodes are using a self signed certificate, we have to provide it here.
|
||||
ca: crt,
|
||||
// we might need to selectively disable that for tests on swarm-testing or so.
|
||||
// we have to reject them, otherwise our errors returned in the checkServerIdentity are simply not making the call fail.
|
||||
// so in production, rejectUnauthorized must be true.
|
||||
rejectUnauthorized: true,
|
||||
keepAlive: false,
|
||||
checkServerIdentity: (host: string, cert: any) => {
|
||||
// Make sure the certificate is issued to the host we are connected to
|
||||
const err = tls.checkServerIdentity(host, cert);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// we might need to selectively disable that for tests on swarm-testing or so.
|
||||
|
||||
// Pin the public key, similar to HPKP pin-sha25 pinning
|
||||
if (sha256(cert.pubkey) !== pubkey256) {
|
||||
const msg =
|
||||
'Certificate verification error: ' +
|
||||
`The public key of '${cert.subject.CN}' ` +
|
||||
'does not match our pinned fingerprint';
|
||||
return new Error(msg);
|
||||
}
|
||||
|
||||
// Pin the exact certificate, rather than the pub key
|
||||
if (cert.fingerprint256 !== cert256) {
|
||||
const msg =
|
||||
'Certificate verification error: ' +
|
||||
`The certificate of '${cert.subject.CN}' ` +
|
||||
'does not match our pinned fingerprint';
|
||||
return new Error(msg);
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
};
|
||||
|
||||
// we're creating a new Agent that will now use the certs we have configured
|
||||
return new https.Agent(sslOptions);
|
||||
};
|
||||
|
||||
export async function getSnodesFromSeedUrl(urlObj: URL): Promise<Array<any>> {
|
||||
const { log } = window;
|
||||
|
||||
|
@ -103,11 +199,14 @@ export async function getSnodesFromSeedUrl(urlObj: URL): Promise<Array<any>> {
|
|||
method: 'get_n_service_nodes',
|
||||
params,
|
||||
};
|
||||
const sslAgent = getSslAgentForSeedNode(urlObj.hostname);
|
||||
|
||||
const fetchOptions = {
|
||||
method: 'POST',
|
||||
timeout: 10000,
|
||||
body: JSON.stringify(body),
|
||||
|
||||
agent: sslAgent,
|
||||
};
|
||||
window.log.info('insecureNodeFetch => plaintext for getSnodesFromSeedUrl');
|
||||
|
||||
|
|
|
@ -1,22 +1,18 @@
|
|||
import semver from 'semver';
|
||||
import _ from 'lodash';
|
||||
|
||||
import {
|
||||
abortableIterator,
|
||||
allowOnlyOneAtATime,
|
||||
} from '../../../js/modules/loki_primitives';
|
||||
|
||||
import {
|
||||
getSnodesFromSeedUrl,
|
||||
getVersion,
|
||||
requestSnodesForPubkey,
|
||||
} from './serviceNodeAPI';
|
||||
import { getSnodesFromSeedUrl, requestSnodesForPubkey } from './serviceNodeAPI';
|
||||
|
||||
import {
|
||||
getSwarmNodesForPubkey,
|
||||
updateSwarmNodesForPubkey,
|
||||
} from '../../../ts/data/data';
|
||||
|
||||
import semver from 'semver';
|
||||
import _ from 'lodash';
|
||||
|
||||
export type SnodeEdKey = string;
|
||||
|
||||
const MIN_NODES = 3;
|
||||
|
@ -60,6 +56,7 @@ async function tryGetSnodeListFromLokidSeednode(
|
|||
let snodes = [];
|
||||
try {
|
||||
const tryUrl = new URL(seedNode.url);
|
||||
|
||||
snodes = await getSnodesFromSeedUrl(tryUrl);
|
||||
// throw before clearing the lock, so the retries can kick in
|
||||
if (snodes.length === 0) {
|
||||
|
|
Loading…
Reference in a new issue