summaryrefslogtreecommitdiff
path: root/src/utils/crypto/EcbCipher.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils/crypto/EcbCipher.scala')
-rw-r--r--src/utils/crypto/EcbCipher.scala49
1 files changed, 49 insertions, 0 deletions
diff --git a/src/utils/crypto/EcbCipher.scala b/src/utils/crypto/EcbCipher.scala
new file mode 100644
index 0000000..306d5fa
--- /dev/null
+++ b/src/utils/crypto/EcbCipher.scala
@@ -0,0 +1,49 @@
+
+package ixee.cryptopals.utils.crypto
+
+import javax.crypto.Cipher
+import ixee.cryptopals.utils.ConversionUtils._
+import ixee.cryptopals.utils.FunctionUtils._
+import ixee.cryptopals.utils.CryptoUtils._
+import ixee.cryptopals.utils.TupleUtils._
+import ixee.cryptopals.utils.ByteUtils._
+
+class EcbCipher(private[this] val cipher: Cipher, mode: Int) extends IxeeCipher {
+ val blockSize = cipher.getBlockSize
+
+ var leftover: Seq[Byte] = Seq()
+
+ lazy val handleBlock: Seq[Byte] => Seq[Byte] =
+ if (mode == Cipher.ENCRYPT_MODE) encBlock _
+ else decBlock _
+
+ def update(data: Seq[Byte]): Seq[Byte] = {
+ val blocks = blockized(leftover ++ data).tap(updateLeftover)._1
+ blocks.foldLeft(Seq[Byte]())(_ ++ handleBlock(_))
+ }
+
+ private def decBlock(data: Seq[Byte]): Seq[Byte] =
+ cipher.update(data.toArray).toSeq
+
+ private def encBlock(data: Seq[Byte]): Seq[Byte] =
+ cipher.update(data.toArray).toSeq
+ // wouldn't hurt to invalidate this object afterward, but meh
+ // TODO: strip padding!
+ // to do it right really requires writing decryption as its own part
+ // it's already obvious that's necessary, but to do padding stripping
+ // properly, the last block must be withheld until an end() call is made
+ // which is much different stateful behavior from encryption.
+ //
+ // in cryptoUtils for now.
+ def end(): Seq[Byte] =
+ if (mode == Cipher.DECRYPT_MODE) Seq()
+ else cipher.update(pkcs7pad(leftover, blockSize).toArray)
+
+ def blockized(data: Seq[Byte]): (Seq[Seq[Byte]], Seq[Byte]) =
+ groupBlocks <-: data.splitAt(data.length - (data.length % blockSize))
+
+ def groupBlocks: Seq[Byte] => Seq[Seq[Byte]] = _.grouped(blockSize).toSeq
+
+ def updateLeftover(pair: (Seq[Seq[Byte]], Seq[Byte])) =
+ leftover = pair._2
+}