Beispiel #1
0
var createFileId = function () {
    var id = uint8ArrayToHex(Nacl.randomBytes(24));
    if (id.length !== 48 || /[^a-f0-9]/.test(id)) {
        throw new Error('file ids must consist of 48 hex characters');
    }
    return id;
};
Beispiel #2
0
function encryptString (string, pwDerivedKey) {
  var nonce = nacl.randomBytes(nacl.secretbox.nonceLength);
  var encObj = nacl.secretbox(nacl.util.decodeUTF8(string), nonce, pwDerivedKey);
  var encString = { 'encStr': nacl.util.encodeBase64(encObj),
                    'nonce': nacl.util.encodeBase64(nonce)};
  return encString;
};
 return new Promise((resolve, reject) => {
   const salt = tweetnacl.randomBytes(32);
   scrypt(password, salt, logN, blockSize, dkLen, (derivedKey) => {
     const nonce = new Uint8Array(24);
     const encryptedSecretKey = tweetnacl.secretbox(secretKey, nonce, new Uint8Array(derivedKey));
     resolve({ encryptedSecretKey, salt, nonce, logN, blockSize });
   });
 });
Beispiel #4
0
function delete_private_key (name) {
    // FIXME: poor man's secure erase
    for (var i = 0; i < 5; ++i) {
        seed = nacl.randomBytes(nacl.sign.seedLength);
        localStorage.setItem(name, util.btoa(seed));
        localStorage.setItem(name, '');
        localStorage.setItem(name, null);
    }
}
Beispiel #5
0
  var box = function(doc) {
    if (turnedOff) return doc
    if (doc._id.match(/^permit\//)) return doc

    var key = nacl.randomBytes(nacl.secretbox.keyLength)
    var nonce = nacl.randomBytes(nacl.secretbox.nonceLength)

    var ephemeralKey = nacl.box.keyPair()

    var recs = Object.keys(doc.receivers || {})
      .map(function(receiver) {
        return nacl.util.decodeBase64(receiver)
      })
      .concat(receivers)
      .reduce(function(memo, publicKey) {
        var nonce = nacl.randomBytes(nacl.box.nonceLength)
        
        memo[nacl.util.encodeBase64(publicKey)] = {
          nonce: nacl.util.encodeBase64(nonce),
          encryptedKey: nacl.util.encodeBase64(nacl.box(
            key,
            nonce,
            publicKey,
            ephemeralKey.secretKey
          ))
        }

      return memo
    }, {})

    var box = nacl.util.encodeBase64(nacl.secretbox(
      nacl.util.decodeUTF8(JSON.stringify(omit(doc, underscoreProperties))),
      nonce,
      key
    ))

    return assign({
        ephemeral: nacl.util.encodeBase64(ephemeralKey.publicKey),
        nonce: nacl.util.encodeBase64(nonce),
        receivers: recs,
        box: box
      },
      pick(doc, underscoreProperties))
  }
Beispiel #6
0
KeyStore._encryptKey = function (privKey, pwDerivedKey) {

  var privKeyArray = nacl_decodeHex(privKey);
  var nonce = nacl.randomBytes(nacl.secretbox.nonceLength);

  var encKey = nacl.secretbox(privKeyArray, nonce, pwDerivedKey);
  encKey = { 'key': nacl.util.encodeBase64(encKey), 'nonce': nacl.util.encodeBase64(nonce)};

  return encKey;
};
Beispiel #7
0
const keyPair = module.exports.keyPair = () => {
    for (;;) {
        let privateKey = new Buffer(Nacl.randomBytes(32)).toString('hex');
        console.log(privateKey);
        let publicKey = privateToPublic(privateKey);
        let ip6 = publicToIp6(publicKey);
        if (IP6_REGEX.test(ip6)) {
            return { privateKey: privateKey, publicKey: publicKey, ip6: ip6 };
        }
    }
};
Beispiel #8
0
function load_private_key (name, force_regenerate) {
    var seed = util.atob(localStorage.getItem(name));
    if (!seed || force_regenerate) {
        seed = nacl.randomBytes(nacl.sign.seedLength);
        localStorage.setItem(name, util.btoa(seed));
        log.debug('new key seed "' + name + '" saved to local storage!');
    } else {
        log.debug('key seed "' + name + '" loaded from local storage!');
    }
    return nacl.sign.keyPair.fromSeed(seed);
}
Beispiel #9
0
  permit.build = function() {
    var nonce = nacl.randomBytes(nacl.box.nonceLength)
    var ephemeralKey = nacl.box.keyPair()

    permit.nonce = nonce
    permit.ephemeral = ephemeralKey.publicKey
    permit.encryptedKey = nacl.box(
      permit.databaseKey.secretKey,
      nonce,
      sessionKey.publicKey,
      ephemeralKey.secretKey
    )

    return permit
  }
Beispiel #10
0
      .reduce(function(memo, publicKey) {
        var nonce = nacl.randomBytes(nacl.box.nonceLength)
        
        memo[nacl.util.encodeBase64(publicKey)] = {
          nonce: nacl.util.encodeBase64(nonce),
          encryptedKey: nacl.util.encodeBase64(nacl.box(
            key,
            nonce,
            publicKey,
            ephemeralKey.secretKey
          ))
        }

      return memo
    }, {})
Beispiel #11
0
Create = function (bk, algo, language) {
    let secret = Nacl.randomBytes(16);
    let keyPair;
    switch (bk) {
        case "cosmos":
            keyPair = CosmosKeyPair.Create(secret, algo);
    }
    if (keyPair) {
        let seed = Wordcodec.BytesToWords(keyPair.secret, language);
        let phrase = seed.toString().replace(/,/g, " ");
        return {
            "address": keyPair.address,
            "phrase": phrase,
            "privateKey": keyPair.privateKey,
            "publicKey": keyPair.publicKey
        };
    }
};
Beispiel #12
0
function makeHeader(ids, senderInfo, fileInfo) {
  const ephemeral = nacl.box.keyPair()
  const header = {
    version: 1,
    ephemeral: nacl.util.encodeBase64(ephemeral.publicKey),
    decryptInfo: {}
  }

  debug(`Ephemeral public key is ${hex(ephemeral.publicKey)}`)
  debug(`Ephemeral secret key is ${hex(ephemeral.secretKey)}`)

  for (let id of ids) {
    debug(`Adding recipient ${id}`)

    const nonce = nacl.randomBytes(24)
    const publicKey = keyFromId(id)

    debug(`Using nonce ${hex(nonce)}`)

    let decryptInfo = {
      senderID: senderInfo.id,
      recipientID: id,
      fileInfo: fileInfo
    }

    decryptInfo.fileInfo = nacl.util.encodeBase64(nacl.box(
      nacl.util.decodeUTF8(JSON.stringify(decryptInfo.fileInfo)),
      nonce,
      publicKey,
      senderInfo.secretKey
    ))

    decryptInfo = nacl.util.encodeBase64(nacl.box(
      nacl.util.decodeUTF8(JSON.stringify(decryptInfo)),
      nonce,
      publicKey,
      ephemeral.secretKey
    ))

    header.decryptInfo[nacl.util.encodeBase64(nonce)] = decryptInfo
  }

  return JSON.stringify(header)
}
function prepareDataToSend(params) {
  var s0 = nacl.util.encodeBase64(nacl.randomBytes(16)); // S0
  var masterKey = crypto.calculateMasterKey(s0, params.username, params.password, params.kdfParams);
  var walletId = crypto.deriveWalletId(masterKey); // W
  var walletKey = crypto.deriveWalletKey(masterKey); // Kw

  params.kdfParams = JSON.stringify(params.kdfParams);

  params.salt = s0;
  params.rawMasterKey = masterKey;
  params.rawWalletId = walletId;
  params.walletId = sjcl.codec.base64.fromBits(walletId);
  params.rawWalletKey = walletKey;

  params.rawMainData = params.mainData;
  params.mainData = crypto.encryptData(params.mainData, walletKey);
  params.mainDataHash = crypto.sha1(params.mainData);

  params.rawKeychainData = params.keychainData;
  params.keychainData = crypto.encryptData(params.keychainData, walletKey);
  params.keychainDataHash = crypto.sha1(params.keychainData);

  return Promise.resolve(params);
}
Beispiel #14
0
function temporaryFilename() {
  return path.resolve(os.tmpdir(),
      '.mlck-' + hex(nacl.randomBytes(32)) + '.tmp')
}
Beispiel #15
0
nacl.util = require('tweetnacl-util')

var NB_BLOCKS = 100
var BLOCK_LENGTH = 1024

var server = net.createServer()
var client = new net.Socket()

var serverKeyPair = nacl.box.keyPair()
var clientKeyPair = nacl.box.keyPair()

var source = Buffer(NB_BLOCKS * BLOCK_LENGTH)
var sourceServer = Buffer(NB_BLOCKS * BLOCK_LENGTH)

for (var i = 0; i < NB_BLOCKS; i++) {
  var buffer = new Buffer(nacl.randomBytes(BLOCK_LENGTH))
  buffer.copy(source, i * BLOCK_LENGTH)
}

for (i = 0; i < NB_BLOCKS; i++) {
  buffer = new Buffer(nacl.randomBytes(BLOCK_LENGTH))
  buffer.copy(sourceServer, i * BLOCK_LENGTH)
}

var currentBlock = 0
var currentBlockServer = 0
var messageStream
var messageStreamServer

var destination = Buffer(0)
var destinationClient = Buffer(0)
Beispiel #16
0
 /**
  * Create a random `Keypair` object.
  * @returns {Keypair}
  */
 static random() {
   const secret = nacl.randomBytes(32);
   return this.fromRawEd25519Seed(secret);
 }
Beispiel #17
0
export function encryptStream(keyPair, inputStream, outputStream, ids,
    { filename, armor, includeSelf }={}, callback) {
  const browser = isBrowser()

  const fromId = miniLockId(keyPair.publicKey)

  debug(`Our miniLock ID is ${fromId}`)

  const senderInfo = {
    id: fromId,
    secretKey: keyPair.secretKey
  }

  const fileKey   = nacl.randomBytes(32)
  const fileNonce = nacl.randomBytes(16)

  debug(`Using file key ${hex(fileKey)}`)
  debug(`Using file nonce ${hex(fileNonce)}`)

  const encryptor = nacl_.stream.createEncryptor(fileKey, fileNonce,
      ENCRYPTION_CHUNK_SIZE)
  const hash = new BLAKE2s(32)

  // This is where the encrypted chunks go.
  let encrypted = []

  const filenameBuffer = new Buffer(256).fill(0)

  if (typeof filename === 'string') {
    filenameBuffer.write(filename)
  }

  let encryptedDataFile = null

  // The first chunk is the 256-byte null-padded filename. If input is stdin,
  // filename is blank. If the UTF-8-encoded filename is greater than 256
  // bytes, it is truncated.
  encryptChunk(filenameBuffer, encryptor, encrypted, hash)

  let inputByteCount = 0

  inputStream.on('error', error => {
    if (encryptedDataFile) {
      fs.unlink(encryptedDataFile, () => {})
    }

    callback(error)
  })

  inputStream.on('readable', () => {
    const chunk = inputStream.read()
    if (chunk !== null) {
      inputByteCount += chunk.length

      // If input exceeds the 4K threshold (picked arbitrarily), switch from
      // writing to an array to writing to a file. This way we can do
      // extremely large files.
      if (!browser && inputByteCount > 4 * 1024 && Array.isArray(encrypted)) {
        // Generate a random filename for writing encrypted chunks to instead of
        // keeping everything in memory.
        encryptedDataFile = temporaryFilename()

        const stream = fs.createWriteStream(encryptedDataFile)

        for (let chunk of encrypted) {
          stream.write(chunk)
        }

        encrypted = stream
      }

      // Encrypt this chunk.
      encryptChunk(chunk, encryptor, encrypted, hash)
    }
  })

  inputStream.on('end', () => {
    // Finish up with the encryption.
    encryptChunk(null, encryptor, encrypted, hash)

    encryptor.clean()

    // This is the 32-byte BLAKE2 hash of all the ciphertext.
    const fileHash = hash.digest()

    debug(`File hash is ${hex(fileHash)}`)

    const fileInfo = {
      fileKey: nacl.util.encodeBase64(fileKey),
      fileNonce: nacl.util.encodeBase64(fileNonce),
      fileHash: nacl.util.encodeBase64(fileHash)
    }

    // Pack the sender and file information into a header.
    const header = makeHeader(includeSelf ? ids.concat(fromId) : ids,
        senderInfo, fileInfo)

    const headerLength = new Buffer(4)
    headerLength.writeUInt32LE(header.length)

    debug(`Header length is ${hex(headerLength)}`)

    let outputByteCount = 0

    let buffer = new Buffer(0)

    let asciiIndent = 0

    let outputHeader = Buffer.concat([
      // The file always begins with the magic bytes 0x6d696e694c6f636b.
      new Buffer('miniLock'), headerLength, new Buffer(header)
    ])

    if (armor) {
      // https://tools.ietf.org/html/rfc4880#section-6

      buffer = outputHeader.slice(outputHeader.length -
            outputHeader.length % 3)
      outputHeader = asciiArmor(outputHeader.slice(0, outputHeader.length -
              outputHeader.length % 3))

      asciiIndent = outputHeader.length % (ARMOR_WIDTH + 1)

      outputHeader = '-----BEGIN MINILOCK FILE-----\n' +
        'Version: miniLock-cli v' + version + '\n' +
        '\n' +
        outputHeader
    }

    if (outputStream) {
      outputStream.write(outputHeader)
    }

    outputByteCount += outputHeader.length

    if (Array.isArray(encrypted)) {
      encrypted.end = async
    }

    encrypted.end(() => {
      if (Array.isArray(encrypted)) {
        // Wrap array into a stream-like interface.
        encrypted = readableArray(encrypted)
      } else {
        encrypted = fs.createReadStream(encryptedDataFile)
      }

      encrypted.on('error', error => {
        async(() => {
          if (encryptedDataFile) {
            fs.unlink(encryptedDataFile, () => {})
          }

          callback(error)
        })
      })

      encrypted.on('readable', () => {
        let chunk = encrypted.read()
        if (chunk !== null) {
          if (armor) {
            chunk = Buffer.concat([ buffer, chunk ])

            const index = chunk.length - chunk.length % 3

            buffer = chunk.slice(index)
            chunk = asciiArmor(chunk.slice(0, index), asciiIndent)

            asciiIndent = (chunk.length + asciiIndent) % (ARMOR_WIDTH + 1)
          }

          if (outputStream) {
            outputStream.write(chunk)
          }

          outputByteCount += chunk.length
        }
      })

      encrypted.on('end', () => {
        if (armor) {
          const chunk = asciiArmor(buffer, asciiIndent) +
            '\n-----END MINILOCK FILE-----\n'

          if (outputStream) {
            outputStream.write(chunk)
          }

          outputByteCount += chunk.length
        }

        async(() => {
          if (encryptedDataFile) {
            // Attempt to delete the temporary file, but ignore any error.
            fs.unlink(encryptedDataFile, () => {})
          }

          callback(null, outputByteCount)
        })
      })
    })
  })
}