anchor.diff:      if !i <> 0 then
           yield (!arr).[0..!i-1] }
   
  -let xorEncrypt (key:byte []) (bytes:byte []) : (byte []) =
  -    let keyLength = key.Length
  -    bytes |> Array.mapi (fun i b -> key.[i % keyLength] ^^^ b)
  -
  -let xorDecrypt (key:byte []) (bytes:byte []) : (byte []) =
  -    let keyLength = key.Length
  -    bytes |> Array.mapi (fun i b -> key.[i % keyLength] ^^^ b)
  -
   let xorBytes (bs0:byte []) (bs1:byte []) : (byte []) =
       Array.zip bs0 bs1 |> Array.map (fun (b0, b1) -> b0 ^^^ b1)
   
  -let ecbEncrypt (key:byte []) (bytes:byte seq) : (byte [] seq) =
  -    let blockSize = key.Length
  -    let blocks = chunk blockSize bytes
  -    let encryptBlock (key:byte []) (plainText:byte []) : (byte []) =
  -        xorEncrypt key plainText
  -    let data =
  -        blocks |> Seq.map (encryptBlock key)
  +// http://failheap-challenge.com/showthread.php?12388-The-Matasano-crypto-challenges/page7
  +let decryptAesEcb (keyBytes:byte []) (iv:byte []) (bytes:byte []) =
  +    let aes = Aes.Create()
  +    aes.BlockSize <- iv.Length * 8
  +    aes.Mode <- CipherMode.ECB
  +    aes.Key <- keyBytes
  +    aes.IV <- iv
  +    aes.Padding <- PaddingMode.None
  +
  +    let result = Array.zeroCreate<byte> (bytes.Length)
  +    use stream = new MemoryStream(bytes)
  +    use decryptor = aes.CreateDecryptor()
  +    use cryptoStream = new CryptoStream(stream, decryptor, CryptoStreamMode.Read)
  +    let bytesRead = cryptoStream.Read(result, 0, bytes.Length)
  +    result
  +
  +let encryptAesEcb (keyBytes:byte []) (iv:byte []) (bytes:byte []) =
  +    let blockSize = iv.Length
  +    let paddedBytes = pkcs7 (byte(blockSize)) bytes
  +    let aes = Aes.Create()
  +    aes.BlockSize <- blockSize * 8
  +    aes.Mode <- CipherMode.ECB
  +    aes.Key <- keyBytes
  +    aes.IV <- iv
  +    aes.Padding <- PaddingMode.None
  +
  +    let data = Array.zeroCreate<byte> (paddedBytes.Length)
  +    use stream = new MemoryStream(data)
  +    use encryptor = aes.CreateEncryptor()
  +    use cryptoStream = new CryptoStream(stream, encryptor, CryptoStreamMode.Write)
  +    cryptoStream.Write(paddedBytes, 0, paddedBytes.Length)
  +    cryptoStream.FlushFinalBlock()
       data
   
  -let ecbDecrypt (key:byte []) (bytes:byte seq) : (byte [] seq) =
  -    let blockSize = key.Length
  -    let blocks = chunk blockSize bytes
  -    let decryptBlock (key:byte []) (plainText:byte []) : (byte []) =
  -        xorDecrypt key plainText
  -    let data =
  -        blocks |> Seq.map (decryptBlock key)
  -    data
  -
  -let cbcEncrypt (key:byte []) (iv:byte []) (bytes:byte seq) : (byte [] seq) =
  -    let blockSize = iv.Length
  -    let blocks = chunk blockSize bytes
  -    let encryptBlock (cipherText:byte []) (plainText:byte []) : (byte []) =
  -        let toEncrypt = xorBytes cipherText plainText
  -        xorEncrypt key toEncrypt
  -    let data =
  -        blocks |> Seq.scan (encryptBlock) iv
  -        // 1st block result is the IV; ignore it
  -        |> Seq.skip 1
  -    data
  -
  -let cbcDecrypt (key:byte []) (iv:byte []) (bytes:byte seq) : (byte [] seq) =
  +//let plainText = "The quick brown fox jumped over the lazy dogs"
  +//let key = "YELLOW SUBMARINE" |> toBytes |> Seq.toArray
  +//let iv = "0000000000000000" |> toBytes |> Seq.toArray
  +//let cipherText = encryptAesEcb key iv (plainText |> toBytes |> Seq.toArray)
  +//let decrypted = decryptAesEcb key iv cipherText
  +//let decryptedText = decrypted |> toText
  +
  +let decryptAesCbc (key:byte []) (iv:byte []) (bytes:byte []) : (byte []) =
       let blockSize = iv.Length
       let blocks = Seq.append [iv] (chunk blockSize bytes)
       let data =
           blocks
  -        |> Seq.map (fun c -> (xorDecrypt key c, c))
  +        |> Seq.map (fun block ->
  +            let iv = Array.zeroCreate<byte> key.Length
  +            (decryptAesEcb key iv block, block))
           |> Seq.windowed 2
           |> Seq.map (fun xs ->
               let (_, prevCipherText) = xs.[0]
               let (currentDecryptedText, _) = xs.[1]
               let plainText = xorBytes prevCipherText currentDecryptedText
               plainText)
  -    data
  +    data |> Seq.collect (fun x -> x) |> Seq.toArray
  +
  +let encryptAesCbc (key:byte []) (iv:byte []) (bytes:byte []) : (byte []) =
  +    let blockSize = iv.Length
  +    let paddedBytes = bytes |> pkcs7 (byte(blockSize))
  +    let blocks = (chunk blockSize paddedBytes)
  +    let data =
  +        blocks
  +        |> Seq.scan (fun prevCipherText currentPlainText ->
  +            let xored = xorBytes prevCipherText currentPlainText
  +            let iv = Array.zeroCreate<byte> key.Length
  +            let currentCipherText = encryptAesEcb key iv xored
  +            currentCipherText) iv
  +            // ignore 1st block as is IV block
  +        |> Seq.skip 1
  +    data |> Seq.collect (fun x -> x) |> Seq.toArray
  +
  +let plainText = "The quick brown fox jumped over the lazy dogs"
  +let key = "YELLOW SUBMARINE" |> toBytes |> Seq.toArray
  +let iv = "0000000000000000" |> toBytes |> Seq.toArray
  +let cipherText = encryptAesCbc key iv (plainText |> toBytes |> Seq.toArray)
  +let decrypted = decryptAesCbc key iv cipherText
  +let decryptedText = decrypted |> toText
   
   let randomBytes (r:Random) (n:int) =
       let bytes = Array.zeroCreate n
  
positive.code: ﻿
  open System
  
  let pkcs7 (blockSize:byte) (bytes:byte []) : (byte []) =
      let paddingCount = int(blockSize) - (bytes.Length % int(blockSize))
      let paddingByte = byte(paddingCount)
      (bytes |> Array.toList) @ (List.replicate paddingCount paddingByte) |> List.toArray
  
  
  // http://stackoverflow.com/questions/716452/f-array-chunk-for-sequence
  let chunk n xs = seq {
  
negative.code:     let key = randomAesKey r
      let prefix = randomBytes r (r.Next (5, 10))
      let postfix = randomBytes r (r.Next (5, 10))
      let bs = [prefix;bytes;postfix] |> Array.concat
      let encryptedBytes =
          match (r.NextDouble () > 0.5) with
          | true ->
              let iv = Array.zeroCreate<byte> 16
              encryptAesEcb key iv bs
          | false ->
              let iv = randomAesKey r
              encryptAesCbc key iv bs
      encryptedBytes
  
  type EncryptionType =
      | ECB
      | CBC
  
  let detectEcbOrCbc (bytes:byte []) : (EncryptionType) =
      let blocks = chunk 16 bytes
      let setBlocks = blocks |> Set.ofSeq
      let setLength = setBlocks |> Set.count
      let blocksLength = blocks |> Seq.length
      match setLength = blocksLength with
      | true -> CBC
      | false -> ECB
      
  let r = new Random(271)
  
  
  let doit (r:Random) =
      let plainText = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" |> toBytes |> Seq.toArray
      let encrypted = encryptRandom r plainText
      detectEcbOrCbc encrypted
  