Repository: mozilla/send
File: app/fileSender.js (JavaScript)

Code before:
import Nanobus from 'nanobus';
import { arrayToB64, b64ToArray, bytes } from './utils';

async function getAuthHeader(authKey, nonce) {
  const sig = await window.crypto.subtle.sign(
    {
      name: 'HMAC'
    },
    authKey,
    b64ToArray(nonce)
  );
  return `send-v1 ${arrayToB64(new Uint8Array(sig))}`;
}

async function sendPassword(file, authKey, rawAuth) {
  const authHeader = await getAuthHeader(authKey, file.nonce);
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.onreadystatechange = () => {
      if (xhr.readyState === XMLHttpRequest.DONE) {
        const nonce = xhr.getResponseHeader('WWW-Authenticate').split(' ')[1];
        file.nonce = nonce;
        if (xhr.status === 200) {
          return resolve(xhr.response);
        }
        reject(new Error(xhr.status));
      }
    };
    xhr.onerror = () => reject(new Error(0));
    xhr.ontimeout = () => reject(new Error(0));
    xhr.open('post', `/api/password/${file.id}`);
    xhr.setRequestHeader('Authorization', authHeader);
    xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.responseType = 'json';
    xhr.timeout = 2000;
    xhr.send(JSON.stringify({ auth: arrayToB64(new Uint8Array(rawAuth)) }));
  });
}

export default class FileSender extends Nanobus {
  constructor(file) {
    super('FileSender');
    this.file = file;
    this.msg = 'importingFile';
    this.progress = [0, 1];
    this.cancelled = false;
    this.iv = window.crypto.getRandomValues(new Uint8Array(12));
    this.uploadXHR = new XMLHttpRequest();
    this.rawSecret = window.crypto.getRandomValues(new Uint8Array(16));

Review comment (security):
Do you want me to revert this removed code back. If in case the `status=401` then the below code would help to reset the `file.nonce`
```javascript
if (xhr.status === 401) {
 const nonce = xhr.getResponseHeader('WWW-Authenticate').split(' ')[1];
 file.nonce = nonce;
}
```


Code after:
import Nanobus from 'nanobus';
import { arrayToB64, b64ToArray, bytes } from './utils';

async function getAuthHeader(authKey, nonce) {
  const sig = await window.crypto.subtle.sign(
    {
      name: 'HMAC'
    },
    authKey,
    b64ToArray(nonce)
  );
  return `send-v1 ${arrayToB64(new Uint8Array(sig))}`;
}

async function sendPassword(file, authKey, rawAuth) {
  const authHeader = await getAuthHeader(authKey, file.nonce);
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.onreadystatechange = () => {
      if (xhr.readyState === XMLHttpRequest.DONE) {
        if (xhr.status === 200) {
          const nonce = xhr.getResponseHeader('WWW-Authenticate').split(' ')[1];
          file.nonce = nonce;
          return resolve(xhr.response);
        }
        reject(new Error(xhr.status));
      }
    };
    xhr.onerror = () => reject(new Error(0));
    xhr.ontimeout = () => reject(new Error(0));
    xhr.open('post', `/api/password/${file.id}`);
    xhr.setRequestHeader('Authorization', authHeader);
    xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.responseType = 'json';
    xhr.timeout = 2000;
    xhr.send(JSON.stringify({ auth: arrayToB64(new Uint8Array(rawAuth)) }));
  });
}

export default class FileSender extends Nanobus {
  constructor(file) {
    super('FileSender');
    this.file = file;
    this.msg = 'importingFile';
    this.progress = [0, 1];
    this.cancelled = false;
    this.iv = window.crypto.getRandomValues(new Uint8Array(12));
    this.uploadXHR = new XMLHttpRequest();
    this.rawSecret = window.crypto.getRandomValues(new Uint8Array(16));