Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sign/Verify message: fix signing with special characters #1673

Merged
merged 1 commit into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions backends/Eclair.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ export default class Eclair {

url = url.slice(-1) === '/' ? url : url + '/';
const headers = {
Authorization: 'Basic ' + Base64Utils.btoa(':' + password),
Authorization:
'Basic ' + Base64Utils.encodeStringToBase64(':' + password),
'Content-Type': 'application/x-www-form-urlencoded'
};
const body = querystring.stringify(params);
Expand Down Expand Up @@ -463,11 +464,11 @@ export default class Eclair {

signMessage = (message: string) =>
this.api('signmessage', {
msg: Base64Utils.btoa(message)
msg: Base64Utils.encodeStringToBase64(message)
});
verifyMessage = (data: any) =>
this.api('verifymessage', {
msg: Base64Utils.btoa(data.msg),
msg: Base64Utils.encodeStringToBase64(data.msg),
sig: data.signature
});
lnurlAuth = async (r_hash: string) => {
Expand Down
4 changes: 2 additions & 2 deletions backends/LND.ts
Original file line number Diff line number Diff line change
Expand Up @@ -391,11 +391,11 @@ export default class LND {
this.postRequest('/v2/wallet/accounts/import', data);
signMessage = (message: string) =>
this.postRequest('/v1/signmessage', {
msg: Base64Utils.btoa(message)
msg: Base64Utils.encodeStringToBase64(message)
});
verifyMessage = (data: any) =>
this.postRequest('/v1/verifymessage', {
msg: Base64Utils.btoa(data.msg),
msg: Base64Utils.encodeStringToBase64(data.msg),
signature: data.signature
});
lnurlAuth = async (r_hash: string) => {
Expand Down
4 changes: 2 additions & 2 deletions backends/LightningNodeConnect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -332,14 +332,14 @@ export default class LightningNodeConnect {
.then((data: walletrpc.ImportAccountResponse) => snakeize(data));
signMessage = async (message: string) =>
await this.lnc.lnd.lightning
.signMessage({ msg: Base64Utils.btoa(message) })
.signMessage({ msg: Base64Utils.encodeStringToBase64(message) })
.then((data: lnrpc.SignMessageResponse) => snakeize(data));
verifyMessage = async (req: lnrpc.VerifyMessageRequest) =>
await this.lnc.lnd.lightning
.verifyMessage({
msg:
typeof req.msg === 'string'
? Base64Utils.btoa(req.msg)
? Base64Utils.encodeStringToBase64(req.msg)
: req.msg,
signature: req.signature
})
Expand Down
2 changes: 1 addition & 1 deletion components/NodeIdenticon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export default function NodeIdenticon({

return (
<View style={{ borderRadius: rounded ? width : 0, overflow: 'hidden' }}>
<SvgXml xml={Base64Utils.atob(data)} />
<SvgXml xml={Base64Utils.decodeBase64ToString(data)} />
</View>
);
}
3 changes: 1 addition & 2 deletions models/Invoice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,8 +275,7 @@ export default class Invoice extends BaseModel {
const encodedMessage =
this.htlcs[0].custom_records[keySendMessageType];
try {
const decoded = Base64Utils.atob(encodedMessage);
return decoded;
return Base64Utils.decodeBase64ToString(encodedMessage);
} catch (e) {
return '';
}
Expand Down
3 changes: 2 additions & 1 deletion stores/FeeStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ export default class FeeStore {
data.chan_point = {
output_index: Number(output_index),
funding_txid_str: funding_txid,
funding_txid_bytes: Base64Utils.btoa(funding_txid) // must encode in base64
funding_txid_bytes:
Base64Utils.encodeStringToBase64(funding_txid) // must encode in base64
};
}

Expand Down
24 changes: 22 additions & 2 deletions utils/Base64Utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
import Base64Utils from './Base64Utils';

describe('Base64Utils', () => {
describe('encodeStringToBase64', () => {
it('Converts string to Base64', () => {
expect(Base64Utils.encodeStringToBase64('test1234')).toEqual(
'dGVzdDEyMzQ='
);
expect(Base64Utils.encodeStringToBase64('✓')).toEqual('4pyT');
expect(Base64Utils.encodeStringToBase64('™“')).toEqual('4oSi4oCc');
});
});

describe('decodeBase64ToString', () => {
it('Converts Base64 to utf8 string', () => {
expect(Base64Utils.decodeBase64ToString('dGVzdDEyMzQ=')).toEqual(
'test1234'
);
expect(Base64Utils.decodeBase64ToString('4pyT')).toEqual('✓');
expect(Base64Utils.decodeBase64ToString('4oSi4oCc')).toEqual('™“');
});
});

describe('utf8ToHexString', () => {
it('Converts utf8 string to hexidecimal string', () => {
it('Converts utf8 string to hexadecimal string', () => {
expect(
Base64Utils.utf8ToHexString('Test string with punctuation.')
).toEqual(
Expand All @@ -21,7 +41,7 @@ describe('Base64Utils', () => {
});

describe('base64ToHex', () => {
it('Converts base64 string to hexidecimal string', () => {
it('Converts base64 string to hexadecimal string', () => {
expect(
Base64Utils.base64ToHex('VGhpcyBpcyB0aGUgZmlyc3QgdGVzdA==')
).toEqual('54686973206973207468652066697273742074657374');
Expand Down
56 changes: 7 additions & 49 deletions utils/Base64Utils.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,8 @@
const chars =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
class Base64Utils {
btoa = (input = '') => {
const str = input;
let output = '';

for (
let block = 0, charCode, i = 0, map = chars;
str.charAt(i | 0) || ((map = '='), i % 1);
output += map.charAt(63 & (block >> (8 - (i % 1) * 8)))
) {
charCode = str.charCodeAt((i += 3 / 4));

if (charCode > 0xff) {
throw new Error(
"'btoa' failed: The string to be encoded contains characters outside of the Latin1 range."
);
}

block = (block << 8) | charCode;
}

return output;
};

atob = (input = '') => {
const str = input.replace(/=+$/, '');
let output = '';

if (str.length % 4 == 1) {
throw new Error(
"'atob' failed: The string to be decoded is not correctly encoded."
);
}
for (
let bc = 0, bs = 0, buffer, i = 0;
(buffer = str.charAt(i++));
~buffer && ((bs = bc % 4 ? bs * 64 + buffer : buffer), bc++ % 4)
? (output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6))))
: 0
) {
buffer = chars.indexOf(buffer);
}

return output;
};
encodeStringToBase64 = (input = '') =>
Buffer.from(input).toString('base64');
decodeBase64ToString = (input = '') =>
Buffer.from(input, 'base64').toString('utf8');

hexStringToByte = (str = '') => {
if (!str) {
Expand All @@ -53,7 +11,7 @@ class Base64Utils {

const a = [];
for (let i = 0, len = str.length; i < len; i += 2) {
a.push(parseInt(str.substr(i, 2), 16));
a.push(parseInt(str.substring(i, i + 2), 16));
}

return new Uint8Array(a);
Expand All @@ -66,7 +24,7 @@ class Base64Utils {
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return this.btoa(binary);
return this.encodeStringToBase64(binary);
};

hexToBase64 = (str = '') => this.byteToBase64(this.hexStringToByte(str));
Expand All @@ -89,7 +47,7 @@ class Base64Utils {
Buffer.from(hexString, 'utf8').toString('hex');

base64ToHex = (base64String: string) => {
const raw = this.atob(base64String);
const raw = this.decodeBase64ToString(base64String);
let result = '';
for (let i = 0; i < raw.length; i++) {
const hex = raw.charCodeAt(i).toString(16);
Expand Down
2 changes: 1 addition & 1 deletion utils/ConnectionFormatUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class ConnectionFormatUtils {
const encodedParams = input.split(
'https://terminal.lightning.engineering#/connect/pair/'
)[1];
const decodedParams = Base64Utils.atob(encodedParams);
const decodedParams = Base64Utils.decodeBase64ToString(encodedParams);
const [pairingPhrase, server] = decodedParams.split('||');

if (
Expand Down