diff --git a/src/main/kotlin/cn/tursom/core/datastruct/AtomicBitSet.kt b/src/main/kotlin/cn/tursom/core/datastruct/AtomicBitSet.kt
index 26e1d09..b3a2307 100644
--- a/src/main/kotlin/cn/tursom/core/datastruct/AtomicBitSet.kt
+++ b/src/main/kotlin/cn/tursom/core/datastruct/AtomicBitSet.kt
@@ -1,7 +1,10 @@
 package cn.tursom.core.datastruct
 
+import cn.tursom.core.randomInt
+import cn.tursom.core.usingTime
 import java.io.Serializable
 import java.lang.reflect.Field
+import java.util.concurrent.atomic.AtomicInteger
 import java.util.concurrent.atomic.AtomicLongArray
 import kotlin.random.Random
 
@@ -26,6 +29,7 @@ class AtomicBitSet(beginSize: Long = 256, val defaultState: Boolean = false) : S
       bitSet.array.forEach { count += it.bitCount }
       return count
     }
+  val upCount get() = trueCount
 
   init {
     val default = if (defaultState) -1L else 0L
@@ -83,7 +87,33 @@ class AtomicBitSet(beginSize: Long = 256, val defaultState: Boolean = false) : S
   }
 
   fun firstUp(): Long {
-    bitSet.forEachIndexed { index, l ->
+    return scanUp(0, bitSet.length())
+  }
+
+  fun randomUpIndex(): Long {
+    val startIndex = Random.nextInt(bitSet.length())
+    var scan = scanUp(startIndex, bitSet.length() - startIndex)
+    if (scan >= 0) return scan
+    scan = scanUp(startIndex - 1, startIndex, false)
+    if (scan >= 0) return scan
+    return -1
+  }
+
+  fun firstDown(): Long {
+    return scanDown(0, bitSet.length())
+  }
+
+  fun getDownIndex(): Long {
+    val startIndex = Random.nextInt(bitSet.length())
+    var scan = scanDown(startIndex, bitSet.length() - startIndex)
+    if (scan >= 0) return scan
+    scan = scanDown(startIndex - 1, startIndex, false)
+    if (scan >= 0) return scan
+    return -1
+  }
+
+  private fun scanUp(fromIndex: Int, length: Int, asc: Boolean = true): Long {
+    bitSet.forEachIndexed(fromIndex, length, asc) { index, l ->
       if (l != 0L) {
         for (i in 0 until 8) {
           if (l and scanArray[i] != 0L) {
@@ -98,19 +128,6 @@ class AtomicBitSet(beginSize: Long = 256, val defaultState: Boolean = false) : S
     return -1
   }
 
-  fun firstDown(): Long {
-    return scanDown(0, bitSet.length())
-  }
-
-  fun getDownIndex(): Long {
-    val startIndex = Random.nextInt(0, bitSet.length())
-    var scan = scanDown(startIndex, bitSet.length() - startIndex)
-    if (scan >= 0) return scan
-    scan = scanDown(startIndex - 1, startIndex, false)
-    if (scan >= 0) return scan
-    return -1
-  }
-
   private fun scanDown(fromIndex: Int, length: Int, asc: Boolean = true): Long {
     bitSet.forEachIndexed(fromIndex, length, asc) { index, l ->
       if (l != -1L) {
@@ -193,21 +210,45 @@ class AtomicBitSet(beginSize: Long = 256, val defaultState: Boolean = false) : S
       array.isAccessible = true
     }
 
-    inline fun AtomicLongArray.forEachIndexed(action: (index: Int, Long) -> Unit) {
+    private inline fun AtomicLongArray.forEachIndexed(action: (index: Int, Long) -> Unit) {
       repeat(length()) {
         action(it, get(it))
       }
     }
 
-    inline fun AtomicLongArray.forEachIndexed(startIndex: Int, length: Int = length(), asc: Boolean = true, action: (index: Int, Long) -> Unit) {
+    private inline fun AtomicLongArray.forEachIndexed(startIndex: Int, length: Int = length(), asc: Boolean = true, action: (index: Int, Long) -> Unit) {
       repeat(length) {
         val index = if (asc) {
           startIndex + it
         } else {
           startIndex - it
         }
+        //scand.incrementAndGet()
         action(index, get(index))
       }
     }
   }
 }
+
+//val scand = AtomicInteger(0)
+
+fun main() {
+  val size = 1000000
+  val bitSet = AtomicBitSet(size.toLong())
+  println(usingTime {
+    repeat(1000) {
+      bitSet.downAll()
+      repeat(size) {
+        val index = bitSet.getDownIndex()
+        bitSet.up(index)
+        repeat(randomInt(0, 3) / 2) {
+          val randomUpIndex = bitSet.randomUpIndex()
+          if (randomUpIndex >= 0) {
+            bitSet.down(randomUpIndex)
+          }
+        }
+      }
+    }
+  })
+  //println(scand.get() / 100)
+}
\ No newline at end of file
diff --git a/src/main/kotlin/cn/tursom/core/encrypt/AbstractPublicKeyEncrypt.kt b/src/main/kotlin/cn/tursom/core/encrypt/AbstractPublicKeyEncrypt.kt
index e9844f5..0bb9244 100644
--- a/src/main/kotlin/cn/tursom/core/encrypt/AbstractPublicKeyEncrypt.kt
+++ b/src/main/kotlin/cn/tursom/core/encrypt/AbstractPublicKeyEncrypt.kt
@@ -1,14 +1,21 @@
 package cn.tursom.core.encrypt
 
+import cn.tursom.core.toHexString
+import cn.tursom.core.toUTF8String
 import java.security.*
+import java.security.interfaces.RSAPublicKey
 import java.security.spec.X509EncodedKeySpec
 import javax.crypto.Cipher
+import kotlin.experimental.xor
+import kotlin.math.min
+import kotlin.random.Random
 
 @Suppress("unused", "MemberVisibilityCanBePrivate")
 abstract class AbstractPublicKeyEncrypt(
   val algorithm: String,
   final override val publicKey: PublicKey,
-  final override val privateKey: PrivateKey? = null
+  final override val privateKey: PrivateKey? = null,
+  val modeOfOperation: BlockCipherModeOfOperation = BlockCipherModeOfOperation.ECB,
 ) : PublicKeyEncrypt {
   val publicKeyEncoded get() = publicKey.encoded!!
   val privateKeyEncoded get() = privateKey?.encoded
@@ -39,67 +46,56 @@ abstract class AbstractPublicKeyEncrypt(
     override fun signature(digest: String): String = this@AbstractPublicKeyEncrypt.signature(digest)
   }
 
-  constructor(algorithm: String, keyPair: KeyPair) : this(algorithm, keyPair.public as PublicKey, keyPair.private as PrivateKey)
-
-  constructor(algorithm: String, keySize: Int = 1024) : this(algorithm, KeyPairGenerator.getInstance(algorithm).let {
-    it.initialize(keySize)
-    it.generateKeyPair()
-  })
-
-  constructor(algorithm: String, publicKey: ByteArray) : this(algorithm, KeyFactory.getInstance(algorithm).generatePublic(X509EncodedKeySpec(publicKey)) as PublicKey)
-
-  override fun encrypt(data: ByteArray, offset: Int, size: Int): ByteArray {
-    return if (size < encryptMaxLen) {
-      encryptCipher.doFinal(data, offset, size)
-    } else {
-      val buffer = ByteArray(((size - 1) / encryptMaxLen + 1) * decryptMaxLen)
-      buffer.copyOf(doFinal(data, offset, size, buffer, encryptCipher, encryptMaxLen))
-    }
+  private val blockCipher: Encrypt = when (modeOfOperation) {
+    BlockCipherModeOfOperation.ECB -> ECBBlockCipher()
+    BlockCipherModeOfOperation.CBC -> CBCBlockCipher()
+    else -> TODO()
   }
 
-  override fun decrypt(data: ByteArray, offset: Int, size: Int): ByteArray {
-    return if (data.size < decryptMaxLen) {
-      decryptCipher.doFinal(data, offset, size)
-    } else {
-      val buffer = ByteArray(size / decryptMaxLen * encryptMaxLen + 11)
-      buffer.copyOf(doFinal(data, offset, size, buffer, decryptCipher, decryptMaxLen))
+  override var encryptInitVector: ByteArray?
+    get() = blockCipher.encryptInitVector
+    set(value) {
+      blockCipher.encryptInitVector = value
+    }
+  override var decryptInitVector: ByteArray?
+    get() = blockCipher.decryptInitVector
+    set(value) {
+      blockCipher.decryptInitVector = value
     }
-  }
 
-  override fun encrypt(data: ByteArray, buffer: ByteArray, bufferOffset: Int, offset: Int, size: Int): Int {
-    return if (data.size < decryptMaxLen) {
-      encryptCipher.doFinal(data, offset, size, buffer, bufferOffset)
-    } else {
-      doFinal(data, offset, size, buffer, encryptCipher, decryptMaxLen, bufferOffset)
-    }
-  }
+  constructor(
+    algorithm: String,
+    keyPair: KeyPair,
+    modeOfOperation: BlockCipherModeOfOperation = BlockCipherModeOfOperation.ECB,
+  ) : this(algorithm, keyPair.public as PublicKey, keyPair.private as PrivateKey, modeOfOperation = modeOfOperation)
 
-  override fun decrypt(data: ByteArray, buffer: ByteArray, bufferOffset: Int, offset: Int, size: Int): Int {
-    return if (data.size < decryptMaxLen) {
-      decryptCipher.doFinal(data, offset, size, buffer, bufferOffset)
-    } else {
-      doFinal(data, offset, size, buffer, decryptCipher, decryptMaxLen, bufferOffset)
-    }
-  }
+  constructor(
+    algorithm: String,
+    keySize: Int = 1024,
+    modeOfOperation: BlockCipherModeOfOperation = BlockCipherModeOfOperation.ECB,
+  ) : this(
+    algorithm,
+    KeyPairGenerator.getInstance(algorithm).let {
+      it.initialize(keySize)
+      it.generateKeyPair()
+    },
+    modeOfOperation = modeOfOperation
+  )
 
-  private fun doFinal(
-    data: ByteArray,
-    offset: Int,
-    size: Int,
-    buffer: ByteArray,
-    cipher: Cipher,
-    blockSize: Int,
-    bufferOffset: Int = 0
-  ): Int {
-    var readPosition = offset
-    var writeIndex = bufferOffset
-    while (readPosition + blockSize < size) {
-      writeIndex += cipher.doFinal(data, readPosition, blockSize, buffer, writeIndex)
-      readPosition += blockSize
-    }
-    writeIndex += cipher.doFinal(data, readPosition, size - readPosition, buffer, writeIndex)
-    return writeIndex - bufferOffset
-  }
+  constructor(
+    algorithm: String,
+    publicKey: ByteArray,
+    modeOfOperation: BlockCipherModeOfOperation = BlockCipherModeOfOperation.ECB,
+  ) : this(
+    algorithm,
+    KeyFactory.getInstance(algorithm).generatePublic(X509EncodedKeySpec(publicKey)) as PublicKey,
+    modeOfOperation = modeOfOperation
+  )
+
+  override fun encrypt(data: ByteArray, offset: Int, size: Int): ByteArray = blockCipher.encrypt(data, offset, size)
+  override fun decrypt(data: ByteArray, offset: Int, size: Int): ByteArray = blockCipher.decrypt(data, offset, size)
+  override fun encrypt(data: ByteArray, buffer: ByteArray, bufferOffset: Int, offset: Int, size: Int): Int = blockCipher.encrypt(data, buffer, bufferOffset, offset, size)
+  override fun decrypt(data: ByteArray, buffer: ByteArray, bufferOffset: Int, offset: Int, size: Int): Int = blockCipher.decrypt(data, buffer, bufferOffset, offset, size)
 
   protected open fun signature(digest: String) = "${digest}with$algorithm"
 
@@ -134,4 +130,162 @@ abstract class AbstractPublicKeyEncrypt(
     result = 31 * result + (privateKey?.hashCode() ?: 0)
     return result
   }
+
+  protected inner class ECBBlockCipher : Encrypt {
+    override fun encrypt(data: ByteArray, offset: Int, size: Int): ByteArray {
+      return if (size < encryptMaxLen) {
+        encryptCipher.doFinal(data, offset, size)
+      } else {
+        val buffer = ByteArray(((size - 1) / encryptMaxLen + 1) * decryptMaxLen)
+        buffer.copyOf(doFinal(data, offset, size, buffer, encryptCipher, encryptMaxLen))
+      }
+    }
+
+    override fun decrypt(data: ByteArray, offset: Int, size: Int): ByteArray {
+      return if (data.size < decryptMaxLen) {
+        decryptCipher.doFinal(data, offset, size)
+      } else {
+        val buffer = ByteArray(size / decryptMaxLen * encryptMaxLen + 11)
+        buffer.copyOf(doFinal(data, offset, size, buffer, decryptCipher, decryptMaxLen))
+      }
+    }
+
+    override fun encrypt(data: ByteArray, buffer: ByteArray, bufferOffset: Int, offset: Int, size: Int): Int {
+      return if (data.size < decryptMaxLen) {
+        encryptCipher.doFinal(data, offset, size, buffer, bufferOffset)
+      } else {
+        doFinal(data, offset, size, buffer, encryptCipher, decryptMaxLen, bufferOffset)
+      }
+    }
+
+    override fun decrypt(data: ByteArray, buffer: ByteArray, bufferOffset: Int, offset: Int, size: Int): Int {
+      return if (data.size < decryptMaxLen) {
+        decryptCipher.doFinal(data, offset, size, buffer, bufferOffset)
+      } else {
+        doFinal(data, offset, size, buffer, decryptCipher, decryptMaxLen, bufferOffset)
+      }
+    }
+
+    private fun doFinal(
+      data: ByteArray,
+      offset: Int,
+      size: Int,
+      buffer: ByteArray,
+      cipher: Cipher,
+      blockSize: Int,
+      bufferOffset: Int = 0,
+    ): Int {
+      var readPosition = offset
+      var writeIndex = bufferOffset
+      while (readPosition + blockSize < size) {
+        writeIndex += cipher.doFinal(data, readPosition, blockSize, buffer, writeIndex)
+        readPosition += blockSize
+      }
+      writeIndex += cipher.doFinal(data, readPosition, size - readPosition, buffer, writeIndex)
+      return writeIndex - bufferOffset
+    }
+  }
+
+  protected inner class CBCBlockCipher : Encrypt {
+    override var encryptInitVector: ByteArray? = Random.nextBytes(encryptMaxLen)
+      set(value) {
+        value ?: return
+        field = value
+        encBuf = value
+      }
+    override var decryptInitVector: ByteArray? = null
+      set(value) {
+        field = value
+        decBuf = value
+      }
+
+    private var encBuf = encryptInitVector!!
+    private var decBuf: ByteArray? = decryptInitVector
+
+    override fun encrypt(data: ByteArray, offset: Int, size: Int): ByteArray {
+      val buffer = ByteArray(((size - 1) / encryptMaxLen + 1) * decryptMaxLen)
+      //return buffer.copyOf(encrypt(data, buffer, 0, offset, size))
+      encrypt(data, buffer, 0, offset, size)
+      return buffer
+    }
+
+    override fun encrypt(data: ByteArray, buffer: ByteArray, bufferOffset: Int, offset: Int, size: Int): Int {
+      var end = offset
+      var start: Int
+      var writeIndex = bufferOffset
+      do {
+        start = end
+        end += encryptMaxLen
+        end = min(data.size, end)
+        (0 until end - start).forEach { index ->
+          encBuf[index] = encBuf[index] xor data[start + index]
+        }
+        writeIndex += encryptCipher.doFinal(encBuf, 0, encBuf.size, buffer, writeIndex)
+        //println("${data.size} $start->$end $writeIndex")
+      } while (end < offset + size)
+      return writeIndex - bufferOffset
+    }
+
+    override fun decrypt(data: ByteArray, offset: Int, size: Int): ByteArray {
+      val decryptInitVector = decBuf!!
+      var start: Int
+      var end = offset
+      val buffer = ByteArray(((size - 1) / decryptMaxLen + 1) * encryptMaxLen + 11)
+      var writeIndex = 0
+      do {
+        start = end
+        end += decryptMaxLen
+        end = min(data.size, end)
+        println("${data.size}, $start->$end, ${buffer.size}, $writeIndex")
+        val writeIndexBefore = writeIndex
+        writeIndex += decryptCipher.doFinal(data, start, end - start, buffer, writeIndex)
+        if (start == 0) {
+          repeat(encryptMaxLen) {
+            buffer[it] = buffer[it] xor decryptInitVector[it]
+          }
+        } else {
+          repeat(writeIndex - writeIndexBefore) {
+            buffer[writeIndexBefore + it] = buffer[writeIndexBefore + it] xor data[start + it]
+          }
+        }
+      } while (end < offset + size)
+      decBuf = buffer.copyOfRange(buffer.size - encryptMaxLen, buffer.size)
+      return buffer.copyOf(writeIndex)
+    }
+
+    override fun decrypt(data: ByteArray, buffer: ByteArray, bufferOffset: Int, offset: Int, size: Int): Int {
+      TODO("Not yet implemented")
+    }
+
+    //private fun doFinal(data: ByteArray, buffer: ByteArray, bufferOffset: Int, offset: Int, size: Int, cipher: Cipher): Int {
+    //  var start = offset
+    //  var end = offset
+    //  var writeIndex = bufferOffset
+    //  do {
+    //    end += decryptMaxLen
+    //    end = min(data.size, end)
+    //    encBuf.indices.forEach { index ->
+    //      encBuf[index] = encBuf[index] xor data[start + index]
+    //    }
+    //    writeIndex += cipher.doFinal(encBuf, 0, encBuf.size, buffer, writeIndex)
+    //    start += decryptMaxLen
+    //  } while (end < offset + size)
+    //  return writeIndex - bufferOffset
+    //}
+  }
+
+  companion object {
+    private val random = Random(System.currentTimeMillis())
+  }
+}
+
+
+fun main() {
+  val source = "HelloWorld".repeat(100).toByteArray()
+  val rsa = RSA()
+  val decodeRsa = rsa.public
+  decodeRsa.decryptInitVector = rsa.encryptInitVector
+  val encrypt = rsa.encrypt(source)
+  //println(encrypt.toHexString())
+  println(decodeRsa.decrypt(encrypt).toUTF8String())
 }
\ No newline at end of file
diff --git a/src/main/kotlin/cn/tursom/core/encrypt/BlockCipherModeOfOperation.kt b/src/main/kotlin/cn/tursom/core/encrypt/BlockCipherModeOfOperation.kt
new file mode 100644
index 0000000..d1925fa
--- /dev/null
+++ b/src/main/kotlin/cn/tursom/core/encrypt/BlockCipherModeOfOperation.kt
@@ -0,0 +1,5 @@
+package cn.tursom.core.encrypt
+
+enum class BlockCipherModeOfOperation {
+  ECB, CBC, CFB, OFB, CTR,
+}
\ No newline at end of file
diff --git a/src/main/kotlin/cn/tursom/core/encrypt/Encrypt.kt b/src/main/kotlin/cn/tursom/core/encrypt/Encrypt.kt
index c36e53e..5c24efe 100644
--- a/src/main/kotlin/cn/tursom/core/encrypt/Encrypt.kt
+++ b/src/main/kotlin/cn/tursom/core/encrypt/Encrypt.kt
@@ -3,6 +3,13 @@ package cn.tursom.core.encrypt
 import cn.tursom.core.buffer.ByteBuffer
 
 interface Encrypt {
+  var encryptInitVector: ByteArray?
+    get() = null
+    set(_) {}
+  var decryptInitVector: ByteArray?
+    get() = null
+    set(_) {}
+
   fun encrypt(data: ByteArray, offset: Int = 0, size: Int = data.size - offset): ByteArray
   fun decrypt(data: ByteArray, offset: Int = 0, size: Int = data.size - offset): ByteArray
   fun encrypt(data: ByteArray, buffer: ByteArray, bufferOffset: Int = 0, offset: Int = 0, size: Int = data.size - offset): Int
diff --git a/src/main/kotlin/cn/tursom/core/encrypt/RSA.kt b/src/main/kotlin/cn/tursom/core/encrypt/RSA.kt
index ca9d7e5..cc13f15 100644
--- a/src/main/kotlin/cn/tursom/core/encrypt/RSA.kt
+++ b/src/main/kotlin/cn/tursom/core/encrypt/RSA.kt
@@ -10,28 +10,49 @@ import java.security.spec.X509EncodedKeySpec
 @Suppress("unused", "MemberVisibilityCanBePrivate")
 class RSA(
   publicKey: RSAPublicKey,
-  privateKey: RSAPrivateKey? = null
-) : AbstractPublicKeyEncrypt("RSA", publicKey, privateKey) {
+  privateKey: RSAPrivateKey? = null,
+  modeOfOperation: BlockCipherModeOfOperation = BlockCipherModeOfOperation.ECB,
+) : AbstractPublicKeyEncrypt("RSA", publicKey, privateKey, modeOfOperation = modeOfOperation) {
 
-  val keySize = publicKey.modulus.bitLength()
-  override val decryptMaxLen = keySize / 8
-  override val encryptMaxLen = decryptMaxLen - 11
+  val keySize get() = (publicKey as RSAPublicKey).modulus.bitLength()
+  override val decryptMaxLen get() = keySize / 8
+  override val encryptMaxLen get() = decryptMaxLen - 11
 
-  override  val public by lazy {
+  override val public by lazy {
     if (privateKey == null) {
       this
     } else {
-      RSA(publicKey)
+      RSA(publicKey, modeOfOperation = modeOfOperation)
     }
   }
 
-  constructor(keyPair: KeyPair) : this(keyPair.public as RSAPublicKey, keyPair.private as RSAPrivateKey)
+  constructor(
+    keyPair: KeyPair,
+    modeOfOperation: BlockCipherModeOfOperation = BlockCipherModeOfOperation.ECB,
+  ) : this(
+    keyPair.public as RSAPublicKey,
+    keyPair.private as RSAPrivateKey,
+    modeOfOperation
+  )
 
-  constructor(keySize: Int = 1024) : this(KeyPairGenerator.getInstance("RSA").let {
-    it.initialize(keySize)
-    it.generateKeyPair()
-  })
+  constructor(
+    keySize: Int = 1024,
+    modeOfOperation: BlockCipherModeOfOperation = BlockCipherModeOfOperation.ECB,
+  ) : this(
+    KeyPairGenerator.getInstance("RSA").let {
+      it.initialize(keySize)
+      it.generateKeyPair()
+    },
+    modeOfOperation
+  )
 
-  constructor(publicKey: ByteArray) : this(KeyFactory.getInstance("RSA").generatePublic(X509EncodedKeySpec(publicKey)) as RSAPublicKey)
+  constructor(
+    publicKey: ByteArray,
+    modeOfOperation: BlockCipherModeOfOperation = BlockCipherModeOfOperation.ECB,
+  ) : this(
+    KeyFactory.getInstance("RSA").generatePublic(X509EncodedKeySpec(publicKey)) as RSAPublicKey,
+    null,
+    modeOfOperation
+  )
 }