[caffeine-hx] r662 committed - CTR (counter) encryption modes

0 views
Skip to first unread message

caffe...@googlecode.com

unread,
Feb 26, 2012, 3:14:52 PM2/26/12
to caffein...@googlegroups.com
Revision: 662
Author: damon...@gmail.com
Date: Sun Feb 26 12:13:55 2012
Log: CTR (counter) encryption modes


http://code.google.com/p/caffeine-hx/source/detail?r=662

Added:
/trunk/ext3/chx/crypt/mode/CTR128.hx
/trunk/ext3/chx/crypt/mode/CTR8.hx
Modified:
/trunk/ext3/chx/crypt/Cipher.hx
/trunk/ext3/chx/crypt/CipherParams.hx
/trunk/ext3/chx/crypt/mode/CTR.hx
/trunk/ext3/chx/crypt/mode/IVBase.hx

=======================================
--- /dev/null
+++ /trunk/ext3/chx/crypt/mode/CTR128.hx Sun Feb 26 12:13:55 2012
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, The Caffeine-hx project contributors
+ * Original author : Russell Weir
+ * Contributors:
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CAFFEINE-HX PROJECT CONTRIBUTORS "AS
IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE CAFFEINE-HX PROJECT CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package chx.crypt.mode;
+
+import chx.io.BytesOutput;
+import chx.io.Output;
+
+/**
+ * Counter mode - a 1 byte block streaming mode. This version
+ * increments the counter every 16 bytes (128 bits), regardless
+ * of cipher block size.
+ **/
+class CTR128 extends CTR8, implements chx.crypt.IMode {
+ public function new() {
+ super();
+ ctr_inc = 16;
+ }
+
+ #if CAFFEINE_DEBUG
+ /**
+ * Only for testing purposes to make sure that NIST vectors match
+ **/
+ override function getBlockSize() : Int {
+ return 16;
+ }
+ #end
+}
=======================================
--- /dev/null
+++ /trunk/ext3/chx/crypt/mode/CTR8.hx Sun Feb 26 12:13:55 2012
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2012, The Caffeine-hx project contributors
+ * Original author : Russell Weir
+ * Contributors:
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CAFFEINE-HX PROJECT CONTRIBUTORS "AS
IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE CAFFEINE-HX PROJECT CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package chx.crypt.mode;
+
+import chx.io.BytesOutput;
+import chx.io.Output;
+
+/**
+ * Counter mode - a 1 byte block streaming mode. This version updates the
+ * counter on every byte (8 bits)
+ **/
+class CTR8 extends IVBase, implements chx.crypt.IMode {
+ /** Bytes encrypted counter **/
+ var num : Int;
+ /** Point at which to increment counter, in number of bytes **/
+ var ctr_inc : Int;
+
+ public function new() {
+ super();
+ num = 0;
+ ctr_inc = 1;
+ }
+
+ public function toString() {
+ return "ctr";
+ }
+
+ override function getBlockSize() : Int {
+ return 1;
+ }
+
+ override public function updateEncrypt( b : Bytes, out : Output) : Int {
+ #if CAFFEINE_DEBUG
+ trace("updateEncrypt: ");
+ var orig_b = b.sub(0);
+ var orig = out;
+ out = new BytesOutput();
+ #end
+
+ common(b, out);
+
+ #if CAFFEINE_DEBUG
+ var db : Bytes = untyped out.getBytes();
+ out = orig;
+ trace("Plaintext: " + orig_b.toHex());
+ trace("Ciphertext: " + db.toHex());
+ trace("");
+ out.writeBytes(db,0,db.length);
+ #end
+
+ return b.length;
+ }
+
+ override public function updateDecrypt( b : Bytes, out : Output ) : Int {
+ #if CAFFEINE_DEBUG
+ trace("updateDecrypt: ");
+ var orig_b = b.sub(0);
+ var orig = out;
+ out = new BytesOutput();
+ #end
+
+ common(b, out);
+
+ #if CAFFEINE_DEBUG
+ var db : Bytes = untyped out.getBytes();
+ out = orig;
+ trace("Plaintext: " + orig_b.toHex());
+ trace("Ciphertext: " + db.toHex());
+ trace("");
+ out.writeBytes(db,0,db.length);
+ #end
+
+ return b.length;
+ }
+
+ private function common(b:Bytes, out:Output) : Int {
+ var n = b.length;
+ if(b.length != n)
+ return 0;
+
+ var e : Bytes = cipher.encryptBlock(currentIV);
+ #if CAFFEINE_DEBUG
+ trace("Input Block: " + currentIV.toHex());
+ trace("Output Block: " + e.toHex());
+ #end
+ for(i in 0...n) {
+ b.set(i, b.get(i) ^ e.get(i));
+ num++;
+ if(num == ctr_inc) {
+ trace(ctr_inc);
+ num = 0;
+ // increment 'counter'
+ var x = currentIV.length-1;
+ while(x>=0) {
+ currentIV.set(x, currentIV.get(x) + 1);
+ if(currentIV.get(x) != 0)
+ break;
+ x--;
+ }
+ e = cipher.encryptBlock(currentIV);
+ }
+ }
+
+ out.writeBytes(b, 0, n);
+ return n;
+ }
+
+}
=======================================
--- /trunk/ext3/chx/crypt/Cipher.hx Sat Feb 25 21:43:48 2012
+++ /trunk/ext3/chx/crypt/Cipher.hx Sun Feb 26 12:13:55 2012
@@ -26,6 +26,7 @@
*/

package chx.crypt;
+import chx.crypt.mode.IVBase;
import chx.crypt.padding.PadPkcs5;
import chx.io.Output;

@@ -149,4 +150,20 @@
return rv;
}

-}
+ /**
+ * Return the initial IV set for this crypt
+ **/
+ public function getIV() : Bytes {
+ return params.iv;
+ }
+
+ /**
+ * As the IV changes during crypt, this will return its current value
+ **/
+ public function getCurrentIV() : Bytes {
+ if(!Std.is(mode, IVBase))
+ return params.iv;
+ var ivm : IVBase = cast mode;
+ return ivm.iv;
+ }
+}
=======================================
--- /trunk/ext3/chx/crypt/CipherParams.hx Sat Feb 25 21:43:48 2012
+++ /trunk/ext3/chx/crypt/CipherParams.hx Sun Feb 26 12:13:55 2012
@@ -28,9 +28,14 @@
package chx.crypt;

class CipherParams {
- /** the starting iv **/
+ /**
+ * The starting vector for IV modes. Can be null for encryption and will
be randomly
+ * generated, but must be set before decryption. See notes in
chx.crypt.mode.IVBase
+ * on proper IV creation.
+ * @see chx.crypt.mode.IVBase
+ **/
public var iv : Bytes;
- /** random generator used to generate IVs **/
+ /** random generator used to generate IVs. Can be null and will create a
default **/
public var prng : math.prng.Random;
/** Does not have to be set manually, is set by Cipher **/
public var direction : CipherDirection;
=======================================
--- /trunk/ext3/chx/crypt/mode/CTR.hx Sat Feb 25 21:43:48 2012
+++ /trunk/ext3/chx/crypt/mode/CTR.hx Sun Feb 26 12:13:55 2012
@@ -31,93 +31,34 @@
import chx.io.Output;

/**
- * CTR mode
+ * Counter mode - a 1 byte block streaming mode. This version updates the
+ * counter each time the number of bytes crypted matches the cipher block
size
**/
-class CTR extends IVBase, implements chx.crypt.IMode {
- var acc : Bytes;
-
- public function toString() {
- return "ctr";
- }
-
- override public function init(params : CipherParams) : Void {
- super.init(params);
- acc = iv.sub(0, blockSize);
- }
-
- override public function updateEncrypt( b : Bytes, out : Output) : Int {
- #if CAFFEINE_DEBUG
- trace("updateEncrypt: ");
- trace("IV " + iv.toHex());
- trace("Plaintext: " + b.toHex());
- var orig = out;
- out = new BytesOutput();
- #end
-
- var n = blockSize;
- if(b.length != n)
- return 0;
- common(b, out);
-
- #if CAFFEINE_DEBUG
- var db : Bytes = untyped out.getBytes();
- out = orig;
- trace("Output Block: " + db.toHex());
- trace("Ciphertext: " + db.toHex());
- trace("");
- out.writeBytes(db,0,db.length);
- #end
-
- return n;
+class CTR extends CTR8, implements chx.crypt.IMode {
+
+ public function new() {
+ super();
+ num = 0;
+ ctr_inc = 1;
+ }
+
+ override public function toString() {
+ return "ctr";
}

- override public function updateDecrypt( b : Bytes, out : Output ) : Int {
- #if CAFFEINE_DEBUG
- trace("updateDecrypt: ");
- trace("IV " + iv.toHex());
- trace("Plaintext: " + b.toHex());
- var orig = out;
- out = new BytesOutput();
- #end
-
- var n = blockSize;
- if(b.length != n)
- return 0;
- common(b, out);
-
- #if CAFFEINE_DEBUG
- var db : Bytes = untyped out.getBytes();
- out = orig;
- trace("Output Block: " + db.toHex());
- trace("Ciphertext: " + db.toHex());
- trace("");
- out.writeBytes(db,0,db.length);
- #end
-
- return n;
+ override function setCipher(v:IBlockCipher) {
+ super.setCipher(v);
+ if(v != null)
+ ctr_inc = v.blockSize;
+ return v;
}

- private function common(b:Bytes, out:Output) : Int {
- var n = blockSize;
- if(b.length != n)
- return 0;
-
- var e : Bytes = cipher.encryptBlock(acc.sub(0, blockSize));
-
- for(i in 0...n)
- b.set(i, b.get(i) ^ e.get(i));
- #if CAFFEINE_DEBUG
- trace("Input Block: " + b.toHex());
- #end
- var i = n-1;
- while(i>=0) {
- acc.set(i, acc.get(i) + 1);
- if(acc.get(i) != 0)
- break;
- i--;
- }
- return n;
- }
-
-
-}
+ #if CAFFEINE_DEBUG
+ /**
+ * Only for testing purposes to make sure that NIST vectors match
+ **/
+ override function getBlockSize() : Int {
+ return ctr_inc;
+ }
+ #end
+}
=======================================
--- /trunk/ext3/chx/crypt/mode/IVBase.hx Sat Feb 25 21:43:48 2012
+++ /trunk/ext3/chx/crypt/mode/IVBase.hx Sun Feb 26 12:13:55 2012
@@ -31,7 +31,15 @@
import math.prng.IPrng;

/**
-* IV is an abstract base class.
+* IV is an abstract base class for modes requiring initialization vectors.
+* According to NIST:
+* There are two recommended methods for generating unpredictable IVs. The
first
+* method is to apply the forward cipher function, under the same key that
is used
+* for the encryption of the plaintext, to a nonce. The nonce must be a
data block
+* that is unique to each execution of the encryption operation. For
example,
+* the nonce may be a counter, as described in Appendix B, or a message
number.
+* The second method is to generate a random data block using a FIPSapproved
+* random number generator.
**/
class IVBase extends ModeBase {
/**
@@ -54,20 +62,34 @@
sb.addByte(params.prng.next());
params.iv = sb.getBytes();
}
- currentIV = params.iv.sub(0);
+ if(params.iv.length < cipher.blockSize)
+ params.iv = BytesUtil.leftPad(params.iv, cipher.blockSize);
+ currentIV = params.iv.sub(0, cipher.blockSize);
}

public function getIV() : Bytes {
return currentIV;
}

+ override function setCipher(v:IBlockCipher) {
+ super.setCipher(v);
+ if(v != null && currentIV != null && currentIV.length > v.blockSize)
+ currentIV = currentIV.sub(0, v.blockSize);
+ return v;
+ }
+
+ /**
+ * Set the initialization vector.
+ **/
public function setIV( s : Bytes ) : Bytes {
// here we use cipher.blockSize, as it may be different
// than out mode blockSize
- if(s.length % cipher.blockSize != 0 || s.length == 0)
- throw("crypt.iv: invalid length. Expected "+cipher.blockSize+ "
bytes.");
- for(i in 0...cipher.blockSize)
- currentIV.set(i, s.get(i));
+ if(s.length == 0 || (cipher != null && s.length != cipher.blockSize))
+ throw("crypt.iv: invalid length. Expected "+cipher.blockSize+" bytes.");
+ var len = s.length;
+ if(cipher != null && cipher.blockSize < len)
+ len = cipher.blockSize;
+ currentIV = s.sub(0,len);
return s;
}

Reply all
Reply to author
Forward
0 new messages