encryption.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. importScripts('../deps/sjcl.min.js')
  2. function parametersfrombits(seed) {
  3. var out = sjcl.hash.sha512.hash(seed)
  4. return {
  5. 'seed': seed,
  6. 'key': sjcl.bitArray.bitSlice(out, 0, 256),
  7. 'iv': sjcl.bitArray.bitSlice(out, 256, 384),
  8. 'ident': sjcl.bitArray.bitSlice(out, 384, 512)
  9. }
  10. }
  11. function parameters(seed) {
  12. if (typeof seed == 'string') {
  13. seed = sjcl.codec.base64url.toBits(seed)
  14. } else {
  15. seed = sjcl.codec.bytes.toBits(seed)
  16. }
  17. return parametersfrombits(seed)
  18. }
  19. function encrypt(file, seed, id) {
  20. var params = parameters(seed)
  21. var uarr = new Uint8Array(file)
  22. //
  23. // why encrypt twice, safenet-js will handle this
  24. //
  25. //var before = sjcl.codec.bytes.toBits(uarr)
  26. //var prp = new sjcl.cipher.aes(params.key)
  27. //var after = sjcl.mode.ccm.encrypt(prp, before, params.iv)
  28. //var afterarray = new Uint8Array(sjcl.codec.bytes.fromBits(after))
  29. //console.log ( 'uarr : ', uarr );
  30. postMessage({
  31. 'id': id,
  32. 'seed': sjcl.codec.base64url.fromBits(params.seed),
  33. 'ident': sjcl.codec.base64url.fromBits(params.ident),
  34. //'encrypted': new Blob([afterarray], { type: 'application/octet-stream' })
  35. 'encrypted': uarr
  36. })
  37. }
  38. var fileheader = [
  39. 85, 80, 49, 0
  40. ]
  41. function decrypt(file, seed, id) {
  42. var params = parameters(seed)
  43. var uarr = new Uint8Array(file)
  44. //console.log ( 'decrypt : file : ', uarr );
  45. // We support the servers jamming a header in to deter direct linking
  46. var hasheader = true
  47. for (var i = 0; i < fileheader.length; i++) {
  48. if (uarr[i] != fileheader[i]) {
  49. hasheader = false
  50. break
  51. }
  52. }
  53. if (hasheader) {
  54. uarr = uarr.subarray(fileheader.length)
  55. }
  56. //
  57. // why encrypt twice, safenet-js will handle this
  58. //
  59. //var before = sjcl.codec.bytes.toBits(uarr);
  60. //var prp = new sjcl.cipher.aes(params.key);
  61. //var after = sjcl.mode.ccm.decrypt(prp, before, params.iv);
  62. //var afterarray = new Uint8Array(sjcl.codec.bytes.fromBits(after));
  63. // Parse the header, which is a null-terminated UTF-16 string containing JSON
  64. var header = ''
  65. //var headerview = new DataView(afterarray.buffer)
  66. var headerview = new DataView(uarr.buffer)
  67. var i = 0;
  68. for (; ; i++) {
  69. var num = headerview.getUint16(i * 2, false)
  70. if (num == 0) {
  71. break;
  72. }
  73. header += String.fromCharCode(num);
  74. }
  75. var header = JSON.parse(header)
  76. //var data = new Blob([afterarray])
  77. var data = new Blob([uarr])
  78. postMessage({
  79. 'id': id,
  80. 'ident': sjcl.codec.base64url.fromBits(params.ident),
  81. 'header': header,
  82. 'decrypted': data.slice((i * 2) + 2, data.size, header.mime)
  83. })
  84. }
  85. function ident(seed, id) {
  86. var params = parameters(seed)
  87. postMessage({
  88. 'id': id,
  89. 'ident': sjcl.codec.base64url.fromBits(params.ident)
  90. })
  91. }
  92. function onprogress(id, progress) {
  93. postMessage({
  94. 'id': id,
  95. 'eventsource': 'encrypt',
  96. 'loaded': progress,
  97. 'total': 1,
  98. 'type': 'progress'
  99. })
  100. }
  101. onmessage = function (e) {
  102. var progress = onprogress.bind(undefined, e.data.id)
  103. sjcl.mode.ccm.listenProgress(progress)
  104. if (e.data.action == 'decrypt') {
  105. decrypt(e.data.data, e.data.seed, e.data.id)
  106. } else if (e.data.action == 'ident') {
  107. ident(e.data.seed, e.data.id)
  108. } else {
  109. sjcl.random.addEntropy(e.data.entropy, 2048, 'runtime')
  110. encrypt(e.data.data, e.data.seed, e.data.id)
  111. }
  112. sjcl.mode.ccm.unListenProgress(progress)
  113. }