尝试添加不同分组加密工作模式

This commit is contained in:
tursom 2020-11-03 08:53:24 +08:00
parent 4643862bb7
commit 37b2cbfedd
5 changed files with 313 additions and 85 deletions

View File

@ -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)
}

View File

@ -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())
}

View File

@ -0,0 +1,5 @@
package cn.tursom.core.encrypt
enum class BlockCipherModeOfOperation {
ECB, CBC, CFB, OFB, CTR,
}

View File

@ -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

View File

@ -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
)
}