mirror of
				https://github.com/PrivateBin/PrivateBin.git
				synced 2025-11-03 14:55:33 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			115 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			115 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/** @fileOverview CBC mode implementation
 | 
						|
 *
 | 
						|
 * @author Emily Stark
 | 
						|
 * @author Mike Hamburg
 | 
						|
 * @author Dan Boneh
 | 
						|
 */
 | 
						|
 | 
						|
/** @namespace
 | 
						|
 * Dangerous: CBC mode with PKCS#5 padding.
 | 
						|
 *
 | 
						|
 * @author Emily Stark
 | 
						|
 * @author Mike Hamburg
 | 
						|
 * @author Dan Boneh
 | 
						|
 */
 | 
						|
if (sjcl.beware === undefined) {
 | 
						|
  sjcl.beware = {};
 | 
						|
}
 | 
						|
sjcl.beware["CBC mode is dangerous because it doesn't protect message integrity."
 | 
						|
] = function() {
 | 
						|
  sjcl.mode.cbc = {
 | 
						|
    /** The name of the mode.
 | 
						|
     * @constant
 | 
						|
     */
 | 
						|
    name: "cbc",
 | 
						|
    
 | 
						|
    /** Encrypt in CBC mode with PKCS#5 padding.
 | 
						|
     * @param {Object} prp The block cipher.  It must have a block size of 16 bytes.
 | 
						|
     * @param {bitArray} plaintext The plaintext data.
 | 
						|
     * @param {bitArray} iv The initialization value.
 | 
						|
     * @param {bitArray} [adata=[]] The authenticated data.  Must be empty.
 | 
						|
     * @return The encrypted data, an array of bytes.
 | 
						|
     * @throws {sjcl.exception.invalid} if the IV isn't exactly 128 bits, or if any adata is specified.
 | 
						|
     */
 | 
						|
    encrypt: function(prp, plaintext, iv, adata) {
 | 
						|
      if (adata && adata.length) {
 | 
						|
        throw new sjcl.exception.invalid("cbc can't authenticate data");
 | 
						|
      }
 | 
						|
      if (sjcl.bitArray.bitLength(iv) !== 128) {
 | 
						|
        throw new sjcl.exception.invalid("cbc iv must be 128 bits");
 | 
						|
      }
 | 
						|
      var i,
 | 
						|
          w = sjcl.bitArray,
 | 
						|
          xor = w._xor4,
 | 
						|
          bl = w.bitLength(plaintext),
 | 
						|
          bp = 0,
 | 
						|
          output = [];
 | 
						|
 | 
						|
      if (bl&7) {
 | 
						|
        throw new sjcl.exception.invalid("pkcs#5 padding only works for multiples of a byte");
 | 
						|
      }
 | 
						|
    
 | 
						|
      for (i=0; bp+128 <= bl; i+=4, bp+=128) {
 | 
						|
        /* Encrypt a non-final block */
 | 
						|
        iv = prp.encrypt(xor(iv, plaintext.slice(i,i+4)));
 | 
						|
        output.splice(i,0,iv[0],iv[1],iv[2],iv[3]);
 | 
						|
      }
 | 
						|
      
 | 
						|
      /* Construct the pad. */
 | 
						|
      bl = (16 - ((bl >> 3) & 15)) * 0x1010101;
 | 
						|
 | 
						|
      /* Pad and encrypt. */
 | 
						|
      iv = prp.encrypt(xor(iv,w.concat(plaintext,[bl,bl,bl,bl]).slice(i,i+4)));
 | 
						|
      output.splice(i,0,iv[0],iv[1],iv[2],iv[3]);
 | 
						|
      return output;
 | 
						|
    },
 | 
						|
    
 | 
						|
    /** Decrypt in CBC mode.
 | 
						|
     * @param {Object} prp The block cipher.  It must have a block size of 16 bytes.
 | 
						|
     * @param {bitArray} ciphertext The ciphertext data.
 | 
						|
     * @param {bitArray} iv The initialization value.
 | 
						|
     * @param {bitArray} [adata=[]] The authenticated data.  It must be empty.
 | 
						|
     * @return The decrypted data, an array of bytes.
 | 
						|
     * @throws {sjcl.exception.invalid} if the IV isn't exactly 128 bits, or if any adata is specified.
 | 
						|
     * @throws {sjcl.exception.corrupt} if if the message is corrupt.
 | 
						|
     */
 | 
						|
    decrypt: function(prp, ciphertext, iv, adata) {
 | 
						|
      if (adata && adata.length) {
 | 
						|
        throw new sjcl.exception.invalid("cbc can't authenticate data");
 | 
						|
      }
 | 
						|
      if (sjcl.bitArray.bitLength(iv) !== 128) {
 | 
						|
        throw new sjcl.exception.invalid("cbc iv must be 128 bits");
 | 
						|
      }
 | 
						|
      if ((sjcl.bitArray.bitLength(ciphertext) & 127) || !ciphertext.length) {
 | 
						|
        throw new sjcl.exception.corrupt("cbc ciphertext must be a positive multiple of the block size");
 | 
						|
      }
 | 
						|
      var i,
 | 
						|
          w = sjcl.bitArray,
 | 
						|
          xor = w._xor4,
 | 
						|
          bi, bo,
 | 
						|
          output = [];
 | 
						|
          
 | 
						|
      adata = adata || [];
 | 
						|
    
 | 
						|
      for (i=0; i<ciphertext.length; i+=4) {
 | 
						|
        bi = ciphertext.slice(i,i+4);
 | 
						|
        bo = xor(iv,prp.decrypt(bi));
 | 
						|
        output.splice(i,0,bo[0],bo[1],bo[2],bo[3]);
 | 
						|
        iv = bi;
 | 
						|
      }
 | 
						|
 | 
						|
      /* check and remove the pad */
 | 
						|
      bi = output[i-1] & 255;
 | 
						|
      if (bi == 0 || bi > 16) {
 | 
						|
        throw new sjcl.exception.corrupt("pkcs#5 padding corrupt");
 | 
						|
      }
 | 
						|
      bo = bi * 0x1010101;
 | 
						|
      if (!w.equal(w.bitSlice([bo,bo,bo,bo], 0, bi*8),
 | 
						|
                   w.bitSlice(output, output.length*32 - bi*8, output.length*32))) {
 | 
						|
        throw new sjcl.exception.corrupt("pkcs#5 padding corrupt");
 | 
						|
      }
 | 
						|
 | 
						|
      return w.bitSlice(output, 0, output.length*32 - bi*8);
 | 
						|
    }
 | 
						|
  };
 | 
						|
};
 |