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

@ -206,7 +206,6 @@ async function serialSigner(path) {
handleSerialPortResponse: async function (value) {
const {command, commandData} = await this.extractCommand(value)
this.logPublicCommandsResponse(command, commandData)
switch (command) {
case COMMAND_SIGN_PSBT:
@ -243,7 +242,7 @@ async function serialSigner(path) {
console.log(` %c${value}`, 'background: #222; color: red')
}
},
logPublicCommandsResponse: function(command, commandData){
logPublicCommandsResponse: function (command, commandData) {
switch (command) {
case COMMAND_SIGN_PSBT:
case COMMAND_PASSWORD:
@ -595,7 +594,6 @@ async function serialSigner(path) {
.getSharedSecret(this.decryptionKey, hwwPublicKey)
.slice(1, 33)
this.$q.notify({
type: 'positive',
message: 'Secure session created!',
@ -666,15 +664,19 @@ async function serialSigner(path) {
},
sendCommandSecure: async function (command, attrs = []) {
console.log('### sendCommandSecure')
const message = [command].concat(attrs).join(' ')
const encrypted = await encryptMessage2(
const iv = window.crypto.getRandomValues(new Uint8Array(16))
const encrypted = await this.encryptMessage(
this.sharedSecret,
iv,
message.length + ' ' + message
)
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) {
const command = value.split(' ')[0]
@ -695,17 +697,17 @@ async function serialSigner(path) {
},
decryptData: async function (value) {
if (!this.sharedSecret) {
this.$q.notify({
type: 'warning',
message: 'Secure session not established!',
timeout: 10000
})
return '/error Secure session not established!'
}
try {
const messageBytes = nobleSecp256k1.utils.hexToBytes(value)
const decrypted1 = await decryptMessage2(
const ivSize = 32
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,
iv,
messageBytes
)
const data = new TextDecoder().decode(decrypted1)
@ -724,6 +726,20 @@ async function serialSigner(path) {
})
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 () {

View file

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

View file

@ -184,9 +184,6 @@ function findAccountPathIssues(path = '') {
}
}
///////////////
let ivHex = '000102030405060708090a0b0c0d0e0f'
function asciiToUint8Array(str) {
var chars = []
for (var i = 0; i < str.length; ++i) {
@ -195,124 +192,3 @@ function asciiToUint8Array(str) {
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
}