<commit_before>import Ember from 'ember';
import shortid from 'npm:shortid';
import config from '../config/environment';
import InvalidEncryptionError from '../utils/invalid-encryption-error';

var ivSeparator = '|',
    OUT = { direction: "out" },
    IN = { direction: "in" },
    mayBeUnsafe = ' is not encrypted (or properly encrypted). ' +
      'Continuing this chat is not safe.';

var host = window.location.hostname,
    protocolSuffix = window.location.protocol.replace(/^http/, '') + '//',
    port = config.QOTR_PORT ? ':' + config.QOTR_PORT : '',
    hostTemplate = protocolSuffix + host + port,
    wsPrefix = 'ws' + hostTemplate,
    httpPrefix = 'http' + hostTemplate;

var e64 = forge.util.encode64,
    d64 = forge.util.decode64;

function mkMessage() {
  var message = Ember.Object.create.apply(Ember.Object, arguments);
  message['is' + Ember.String.capitalize(message.kind)] = true;

  return message;
}

export default Ember.Object.extend({
  id: null,
  member_id: null,
  nick: null,
  salt: null,
  password: <PASSWORD>,
  socket: null,
  members: null,
  messages: null,
  connected: false,

  init: function () {
    if (!this.id) {
      this.set('id', shortid.generate());
      this.set('salt', forge.random.getBytesSync(128));
      this.set('password', shortid.generate());
    }

    this.set('members', {});
    this.set('messages', Ember.A());

    if (!this.get('nick')) {
      this.set('nick', shortid.generate());
    }
  },

  key: Ember.computed('salt', 'password', function () {
    return forge.pkcs5.pbkdf2(this.get('password'), this.get('salt'), 32, 32);
  }),

  start: function () {
    return Ember.$.post(httpPrefix + '/channels/new', {
      id: this.id,
      meta: e64(this.salt)
    });
  },

  connect: function () {
    var socket = new WebSocket(wsPrefix + '/channels/' + this.id),
        that = this;
    this.socket = socket;
    function setConnected () {
      that.set('connected', socket.readyState === 1);
    }
    this.socket.onopen = setConnected;
    this.socket.onclose = setConnected;
    this.socket.onmessage = function (event) {
        var message = JSON.parse(event.data);
        if (message.sender === null) {
          that.onServerMessage(message);
        } else {
          that.onFriendMessage(message);
        }
    };

    this.pingInterval = setInterval(function () {
      that.send('ping');
    }, 30000);
  },

  disconnect: function () {
    clearInterval(this.pingInterval);

    this.socket.close();
    delete this.socket;
  },

  ivHmac: function (iv) {
    var _hmac = forge.hmac.create();
    _hmac.start('sha256', this.get('key'));
    _hmac.update(iv);
    return _hmac.digest().toHex();
  },

  encrypt: function (str) {
    var iv = forge.random.getBytesSync(32),
        cipher = forge.aes.startEncrypting(this.get('key'), iv),
        input = forge.util.createBuffer(str);
    cipher.update(input);
    cipher.finish();
    return [this.ivHmac(iv), iv, cipher.output.data].map(e64).join(ivSeparator);
  },

  decrypt: function (str) {
    var byteArray = str.split(ivSeparator).map(d64),
        ivHmac = byteArray[0] || '',
        iv = byteArray[1] || '',
        text = byteArray[2] || '',
        ptext = forge.aes.startDecrypting(this.get('key'), iv),
        newBuffer = forge.util.createBuffer(text);

    if (ivHmac !== this.ivHmac(iv) ){
      throw new InvalidEncryptionError();
    }
<commit_msg>Message IV comes before its hmac<commit_after>import Ember from 'ember';
import shortid from 'npm:shortid';
import config from '../config/environment';
import InvalidEncryptionError from '../utils/invalid-encryption-error';

var ivSeparator = '|',
    OUT = { direction: "out" },
    IN = { direction: "in" },
    mayBeUnsafe = ' is not encrypted (or properly encrypted). ' +
      'Continuing this chat is not safe.';

var host = window.location.hostname,
    protocolSuffix = window.location.protocol.replace(/^http/, '') + '//',
    port = config.QOTR_PORT ? ':' + config.QOTR_PORT : '',
    hostTemplate = protocolSuffix + host + port,
    wsPrefix = 'ws' + hostTemplate,
    httpPrefix = 'http' + hostTemplate;

var e64 = forge.util.encode64,
    d64 = forge.util.decode64;

function mkMessage() {
  var message = Ember.Object.create.apply(Ember.Object, arguments);
  message['is' + Ember.String.capitalize(message.kind)] = true;

  return message;
}

export default Ember.Object.extend({
  id: null,
  member_id: null,
  nick: null,
  salt: null,
  password: <PASSWORD>,
  socket: null,
  members: null,
  messages: null,
  connected: false,

  init: function () {
    if (!this.id) {
      this.set('id', shortid.generate());
      this.set('salt', forge.random.getBytesSync(128));
      this.set('password', shortid.generate());
    }

    this.set('members', {});
    this.set('messages', Ember.A());

    if (!this.get('nick')) {
      this.set('nick', shortid.generate());
    }
  },

  key: Ember.computed('salt', 'password', function () {
    return forge.pkcs5.pbkdf2(this.get('password'), this.get('salt'), 32, 32);
  }),

  start: function () {
    return Ember.$.post(httpPrefix + '/channels/new', {
      id: this.id,
      meta: e64(this.salt)
    });
  },

  connect: function () {
    var socket = new WebSocket(wsPrefix + '/channels/' + this.id),
        that = this;
    this.socket = socket;
    function setConnected () {
      that.set('connected', socket.readyState === 1);
    }
    this.socket.onopen = setConnected;
    this.socket.onclose = setConnected;
    this.socket.onmessage = function (event) {
        var message = JSON.parse(event.data);
        if (message.sender === null) {
          that.onServerMessage(message);
        } else {
          that.onFriendMessage(message);
        }
    };

    this.pingInterval = setInterval(function () {
      that.send('ping');
    }, 30000);
  },

  disconnect: function () {
    clearInterval(this.pingInterval);

    this.socket.close();
    delete this.socket;
  },

  ivHmac: function (iv) {
    var _hmac = forge.hmac.create();
    _hmac.start('sha256', this.get('key'));
    _hmac.update(iv);
    return _hmac.digest().toHex();
  },

  encrypt: function (str) {
    var iv = forge.random.getBytesSync(32),
        cipher = forge.aes.startEncrypting(this.get('key'), iv),
        input = forge.util.createBuffer(str);
    cipher.update(input);
    cipher.finish();
    return [iv, this.ivHmac(iv), cipher.output.data].map(e64).join(ivSeparator);
  },

  decrypt: function (str) {
    var byteArray = str.split(ivSeparator).map(d64),
        iv = byteArray[0] || '',
        ivHmac = byteArray[1] || '',
        text = byteArray[2] || '',
        ptext = forge.aes.startDecrypting(this.get('key'), iv),
        newBuffer = forge.util.createBuffer(text);

    if (ivHmac !== this.ivHmac(iv) ){
      throw new InvalidEncryptionError();
    }

{'fraction_non_alphanumeric': 0.16673979815708645, 'fraction_numerical': 0.010823460582126665, 'mean_word_length': 2.9663573085846866, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6304475', 'n_tokens_mistral': 2339, 'n_tokens_neox': 2244, 'n_words': 447}