feat: use random IV for each request

This commit is contained in:
Vlad Stan 2022-08-12 16:52:55 +03:00
parent 19dfef6044
commit a32754610a
3 changed files with 29 additions and 138 deletions

View file

@ -207,7 +207,6 @@ async function serialSigner(path) {
const {command, commandData} = await this.extractCommand(value) const {command, commandData} = await this.extractCommand(value)
this.logPublicCommandsResponse(command, commandData) this.logPublicCommandsResponse(command, commandData)
switch (command) { switch (command) {
case COMMAND_SIGN_PSBT: case COMMAND_SIGN_PSBT:
this.handleSignResponse(commandData) this.handleSignResponse(commandData)
@ -243,7 +242,7 @@ async function serialSigner(path) {
console.log(` %c${value}`, 'background: #222; color: red') console.log(` %c${value}`, 'background: #222; color: red')
} }
}, },
logPublicCommandsResponse: function(command, commandData){ logPublicCommandsResponse: function (command, commandData) {
switch (command) { switch (command) {
case COMMAND_SIGN_PSBT: case COMMAND_SIGN_PSBT:
case COMMAND_PASSWORD: case COMMAND_PASSWORD:
@ -595,7 +594,6 @@ async function serialSigner(path) {
.getSharedSecret(this.decryptionKey, hwwPublicKey) .getSharedSecret(this.decryptionKey, hwwPublicKey)
.slice(1, 33) .slice(1, 33)
this.$q.notify({ this.$q.notify({
type: 'positive', type: 'positive',
message: 'Secure session created!', message: 'Secure session created!',
@ -666,15 +664,19 @@ async function serialSigner(path) {
}, },
sendCommandSecure: async function (command, attrs = []) { sendCommandSecure: async function (command, attrs = []) {
console.log('### sendCommandSecure')
const message = [command].concat(attrs).join(' ') const message = [command].concat(attrs).join(' ')
const iv = window.crypto.getRandomValues(new Uint8Array(16))
const encrypted = await encryptMessage2( const encrypted = await this.encryptMessage(
this.sharedSecret, this.sharedSecret,
iv,
message.length + ' ' + message message.length + ' ' + message
) )
const encryptedHex = nobleSecp256k1.utils.bytesToHex(encrypted) const encryptedHex = nobleSecp256k1.utils.bytesToHex(encrypted)
await this.writer.write(encryptedHex + '\n') const encryptedIvHex = nobleSecp256k1.utils.bytesToHex(iv)
console.log('### encryptedIvHex', encryptedIvHex)
await this.writer.write(encryptedHex + encryptedIvHex + '\n')
}, },
extractCommand: async function (value) { extractCommand: async function (value) {
const command = value.split(' ')[0] const command = value.split(' ')[0]
@ -695,17 +697,17 @@ async function serialSigner(path) {
}, },
decryptData: async function (value) { decryptData: async function (value) {
if (!this.sharedSecret) { if (!this.sharedSecret) {
this.$q.notify({
type: 'warning',
message: 'Secure session not established!',
timeout: 10000
})
return '/error Secure session not established!' return '/error Secure session not established!'
} }
try { try {
const messageBytes = nobleSecp256k1.utils.hexToBytes(value) const ivSize = 32
const decrypted1 = await decryptMessage2( const messageHex = value.substring(0, value.length - ivSize)
const ivHex = value.substring(value.length - ivSize)
const messageBytes = nobleSecp256k1.utils.hexToBytes(messageHex)
const iv = nobleSecp256k1.utils.hexToBytes(ivHex)
const decrypted1 = await this.decryptMessage(
this.sharedSecret, this.sharedSecret,
iv,
messageBytes messageBytes
) )
const data = new TextDecoder().decode(decrypted1) const data = new TextDecoder().decode(decrypted1)
@ -724,6 +726,20 @@ async function serialSigner(path) {
}) })
return '/error Failed to decrypt message from device!' return '/error Failed to decrypt message from device!'
} }
},
encryptMessage: async function (key, iv, message) {
while (message.length % 16 !== 0) message += ' '
const encodedMessage = asciiToUint8Array(message)
const aesCbc = new aesjs.ModeOfOperation.cbc(key, iv)
const encryptedBytes = aesCbc.encrypt(encodedMessage)
return encryptedBytes
},
decryptMessage: async function (key, iv, encryptedBytes) {
const aesCbc = new aesjs.ModeOfOperation.cbc(key, iv)
const decryptedBytes = aesCbc.decrypt(encryptedBytes)
return decryptedBytes
} }
}, },
created: async function () { created: async function () {

View file

@ -47,7 +47,6 @@
if (checkInt(arg.length) && checkInts(arg)) { if (checkInt(arg.length) && checkInts(arg)) {
return new Uint8Array(arg); return new Uint8Array(arg);
} }
console.log('### aes encypt')
throw new Error('unsupported array-like object'); throw new Error('unsupported array-like object');
} }

View file

@ -184,9 +184,6 @@ function findAccountPathIssues(path = '') {
} }
} }
///////////////
let ivHex = '000102030405060708090a0b0c0d0e0f'
function asciiToUint8Array(str) { function asciiToUint8Array(str) {
var chars = [] var chars = []
for (var i = 0; i < str.length; ++i) { for (var i = 0; i < str.length; ++i) {
@ -195,124 +192,3 @@ function asciiToUint8Array(str) {
return new Uint8Array(chars) return new Uint8Array(chars)
} }
async function encryptMessage(key, message) {
// The iv must never be reused with a given key.
// iv = window.crypto.getRandomValues(new Uint8Array(16));
iv = new Uint8Array([
0x00,
0x01,
0x02,
0x03,
0x04,
0x05,
0x06,
0x07,
0x08,
0x09,
0x0a,
0x0b,
0x0c,
0x0d,
0x0e,
0x0f
])
const ciphertext = await window.crypto.subtle.encrypt(
{
name: 'AES-CBC',
iv
},
key,
message
)
console.log('### #####################################')
return new Uint8Array(ciphertext)
}
async function encryptMessage2(key, message) {
// The iv must never be reused with a given key.
// iv = window.crypto.getRandomValues(new Uint8Array(16));
while (message.length % 16 !== 0) message += ' '
const encodedMessage = asciiToUint8Array(message)
iv = new Uint8Array([
0x00,
0x01,
0x02,
0x03,
0x04,
0x05,
0x06,
0x07,
0x08,
0x09,
0x0a,
0x0b,
0x0c,
0x0d,
0x0e,
0x0f
])
const aesCbc = new aesjs.ModeOfOperation.cbc(key, iv)
const encryptedBytes = aesCbc.encrypt(encodedMessage)
console.log('### #####################################')
return encryptedBytes
}
async function decryptMessage(key, ciphertext) {
iv = new Uint8Array([
0x00,
0x01,
0x02,
0x03,
0x04,
0x05,
0x06,
0x07,
0x08,
0x09,
0x0a,
0x0b,
0x0c,
0x0d,
0x0e,
0x0f
])
let decrypted = await window.crypto.subtle.decrypt(
{
name: 'AES-CBC',
iv
},
key,
ciphertext
)
return decrypted
}
async function decryptMessage2(key, encryptedBytes) {
iv = new Uint8Array([
0x00,
0x01,
0x02,
0x03,
0x04,
0x05,
0x06,
0x07,
0x08,
0x09,
0x0a,
0x0b,
0x0c,
0x0d,
0x0e,
0x0f
])
const aesCbc = new aesjs.ModeOfOperation.cbc(key, iv)
const decryptedBytes = aesCbc.decrypt(encryptedBytes)
console.log('### decryptedBytes', decryptedBytes)
return decryptedBytes
}