Skip to content

Commit

Permalink
hip2: remove hip2-dane dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
rithvikvibhu committed Jun 29, 2022
1 parent db36ca4 commit 4743825
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 30 deletions.
95 changes: 95 additions & 0 deletions app/background/hip2/hip2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Based on:
// - https://github.com/Falci/well-known-wallets-hns/blob/master/lib.js
// - https://github.com/lukeburns/hip2-dane/blob/main/index.js

import isValidAddress from '../../utils/verifyAddress';

const hdns = require('hdns');
const https = require('https');

const MAX_LENGTH = 90;

const verifyTLSA = async (cert, host) => {
try {
const tlsa = await hdns.resolveTLSA(host, 'tcp', 443);
const valid = hdns.verifyTLSA(tlsa[0], cert.raw);

return valid;
} catch (e) {
console.error(e);
return false;
}
};

export async function getAddress(host, network) {
let certificate = undefined;

return new Promise(async (resolve, reject) => {
const options = {
rejectUnauthorized: false,
lookup: hdns.legacy,
};

const req = https.get(`https://${host}/.well-known/wallets/HNS`, options, res => {
res.setEncoding('utf8');

let data = '';

res.on('data', chunk => {
// undefined = not yet stored
// null = socket destroyed
// object = may contain certificate
if (certificate === undefined) {
certificate = res.socket.getPeerCertificate(false);
}

const newLine = chunk.indexOf('\n');
if (newLine >= 0) {
req.destroy();
chunk = chunk.slice(0, newLine);
}

if (data.length + chunk.length > MAX_LENGTH) {
if (!req.destroyed) {
req.destroy();
}
const error = new Error('response too large');
error.code = 'ELARGE';
return reject(error);
}

data += chunk;
})

res.on('end', async () => {
const dane = await verifyTLSA(certificate, host);
if (!dane) {
const error = new Error('invalid DANE');
error.code = 'EINSECURE';
return reject(error);
}

if (res.statusCode >= 400) {
const error = new Error(res.statusMessage);
error.code = res.statusCode;
return reject(error);
}

const addr = data.trim();

if (!isValidAddress(addr, network)) {
const error = new Error('invalid address');
error.code = 'EINVALID';
return reject(error);
}

return resolve(data.trim());
});
});

req.on('error', reject);
req.end();
});
}

export const { setServers } = hdns;
39 changes: 20 additions & 19 deletions app/background/hip2/service.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import { SET_HIP2_PORT } from '../../ducks/hip2Reducer';
import { get, put } from '../db/service';
import { dispatchToMainWindow } from '../../mainWindow';
import { service } from '../node/service';
const { fetchAddress, setServers } = require('hip2-dane');
import { setServers, getAddress } from './hip2';
import isValidAddress from '../../utils/verifyAddress';

const HIP2_PORT = 'hip2/port';

async function getPort () {
async function getPort() {
const hip2Port = await get(HIP2_PORT);
if (hip2Port !== null) {
return hip2Port;
Expand All @@ -15,36 +16,36 @@ async function getPort () {
return 9892;
}

async function setPort (port) {
async function setPort(port) {
await put(HIP2_PORT, port);
dispatchToMainWindow({
type: SET_HIP2_PORT,
payload: port
});
}

const sName = 'Hip2';
async function fetchAddress(host) {
const network = service.network.type;

const networkPrefix = {
simnet: 'ss1',
testnet: 'ts1',
main: 'hs1',
regtest: 'rs1'
};
// Host should not be a Handshake address
if (isValidAddress(host, network)) {
const error = new Error('alias cannot be a valid address')
error.code = 'ECOLLISION'
throw error;
}

return await getAddress(host, network);
}

const sName = 'Hip2';

const methods = {
getPort,
setPort,
fetchAddress: async address => await fetchAddress(address, {
token: 'HNS',
maxLength: 90,
validate: addr => {
return typeof addr === 'string' && addr.slice(0, 3) === networkPrefix[service.network.type];
}
}),
setServers
fetchAddress,
setServers,
};

export async function start (server) {
export async function start(server) {
server.withService(sName, methods);
}
20 changes: 10 additions & 10 deletions app/components/SendModal/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class SendModal extends Component {
if (input) {
this.setState({ hip2Loading: true })

// delay lookup by 120ms
// delay lookup by 120ms
setTimeout(() => {
// abort lookup if input has changed
if (!(this.state.hip2Input && this.state.hip2To === input)) return
Expand All @@ -124,7 +124,7 @@ class SendModal extends Component {
hip2Error = this.context.t('hip2InvalidAddress')
} else if (err.code === 'ECOLLISION') {
hip2Error = this.context.t('hip2InvalidAlias')
} else if (err.code === -1) {
} else if (err.code === 'EINSECURE') {
hip2Error = this.context.t('hip2InvalidTLSA')
} else {
hip2Error = this.context.t('hip2AddressNotFound')
Expand Down Expand Up @@ -310,20 +310,20 @@ class SendModal extends Component {
<div className="send__to">
<div className="send__label">{t('sendToLabel')}</div>
<div className="send__input" key="send-input">
{hip2Input &&
{hip2Input &&
<span className="send__prefix">{to ? (
<img src={LockSVG} />
) : ( hip2Loading ?
<img className="send__hip2-loading" src={RingsSVG} />
) : ( hip2Loading ?
<img className="send__hip2-loading" src={RingsSVG} />
: '@')}
</span>}
<input
type="text"
placeholder={hip2Input ?
t('recipientHip2Address') :
(hip2Enabled ?
t('recipientAddressHip2Enabled') :
(!this.props.noDns ?
placeholder={hip2Input ?
t('recipientHip2Address') :
(hip2Enabled ?
t('recipientAddressHip2Enabled') :
(!this.props.noDns ?
t('recipientAddressHip2Syncing') :
t('recipientAddress')
)
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@
"copy-to-clipboard": "3.3.1",
"deep-equal": "2.0.1",
"electron-debug": "3.2.0",
"hip2-dane": "0.4.2",
"history": "4.7.2",
"hs-airdrop": "^0.10.0",
"hs-client": "=0.0.10",
Expand Down

0 comments on commit 4743825

Please sign in to comment.