Skip to content

Commit

Permalink
Implemented InvCipher function for AES
Browse files Browse the repository at this point in the history
  • Loading branch information
chRyNaN committed Aug 27, 2024
1 parent f5b382e commit bf99bbd
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 1 deletion.
38 changes: 38 additions & 0 deletions aes/src/commonMain/kotlin/com/mooncloak/kodetools/aes/InvCipher.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.mooncloak.kodetools.aes

/**
* Represents the general decryption function for executing the AES (Advanced Encryption Standard).
*
* @param [input] The data input, which is a block represented as a linear array of 16 bytes.
*
* @param [numberOfRounds] The number of rounds, "Nr", for the instance. This value is dependent on the key bit size.
* The following values are supported: AES-128: `10`, for AES-192: `12`, AES-256: `14`.
*
* @param [roundKeys] The keys for each round. This value must be of size [numberOfRounds]. A round key is a block that
* is usually represented as a sequence of four words (16 bytes). The "KEYEXPANSION()" function, defined by the AES
* Specification, takes the block cipher key as input and generates the round keys as output.
*
* @see [AES Specification](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197-upd1.pdf)
*/
internal fun InvCipher(
input: ByteArray,
numberOfRounds: Int,
roundKeys: Array<ByteArray>
): ByteArray {
val state = State(input)

state.addRoundKey(roundKeys.copyOfRange(fromIndex = 4 * numberOfRounds, toIndex = 4 * numberOfRounds + 3))

for (round in (numberOfRounds - 1) downTo 1) {
state.invShiftRows()
state.invSubBytes()
state.addRoundKey(roundKeys.copyOfRange(fromIndex = 4 * round, toIndex = 4 * round + 3))
state.invMixColumns()
}

state.invShiftRows()
state.invSubBytes()
state.addRoundKey(roundKeys.copyOfRange(fromIndex = 0, toIndex = 4))

return state.output()
}
3 changes: 3 additions & 0 deletions aes/src/commonMain/kotlin/com/mooncloak/kodetools/aes/SBox.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,7 @@ internal val sbox: Array<UByteArray> = arrayOf(
ubyteArrayOf(0xe1u, 0xf8u, 0x98u, 0x11u, 0x69u, 0xd9u, 0x8eu, 0x94u, 0x9bu, 0x1eu, 0x87u, 0xe9u, 0xceu, 0x55u, 0x28u, 0xdfu),
ubyteArrayOf(0x8cu, 0xa1u, 0x89u, 0x0du, 0xbfu, 0xe6u, 0x42u, 0x68u, 0x41u, 0x99u, 0x2du, 0x0fu, 0xb0u, 0x54u, 0xbbu, 0x16u)
)

@OptIn(ExperimentalUnsignedTypes::class)
internal val invSbox: Array<UByteArray> = TODO()
//@formatter:on
53 changes: 52 additions & 1 deletion aes/src/commonMain/kotlin/com/mooncloak/kodetools/aes/State.kt
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ internal inline fun State.addRoundKey(roundKey: Array<ByteArray>): State {
}

@OptIn(ExperimentalUnsignedTypes::class)
internal fun State.subBytes(): State {
internal inline fun State.subBytes(): State {
for (r in 0..3) {
for (c in 0..3) {
val x = this[r, c].toInt() and 0x0F
Expand All @@ -142,3 +142,54 @@ internal fun State.subBytes(): State {

return this
}

internal inline fun State.invShiftRows(): State {
for (r in 1..3) {
val temp = ByteArray(4)

for (c in 0..3) {
temp[c] = this[r, (c - r + 4) % 4]
}

for (c in 0..3) {
this[r, c] = temp[c]
}
}

return this
}

@OptIn(ExperimentalUnsignedTypes::class)
internal inline fun State.invSubBytes(): State {
for (r in 0..3) {
for (c in 0..3) {
this[r, c] = invSbox[this[r, c].toInt() ushr 4][this[r, c].toInt() and 0x0f].toByte()
}
}

return this
}

internal inline fun State.invMixColumns(): State {
for (c in 0..3) {
val a = IntArray(4)
val b = IntArray(4)

for (i in 0..3) {
a[i] = this[i, c].toInt() and 0xff
}

//@formatter:off
b[0] = a[0].multiplyGF256(0x0e) xor a[1].multiplyGF256(0x0b) xor a[2].multiplyGF256(0x0d) xor a[3].multiplyGF256(0x09)
b[1] = a[0].multiplyGF256(0x09) xor a[1].multiplyGF256(0x0e) xor a[2].multiplyGF256( 0x0b) xor a[3].multiplyGF256( 0x0d)
b[2] = a[0].multiplyGF256(0x0d) xor a[1].multiplyGF256( 0x09) xor a[2].multiplyGF256( 0x0e) xor a[3].multiplyGF256( 0x0b)
b[3] = a[0].multiplyGF256( 0x0b) xor a[1].multiplyGF256( 0x0d) xor a[2].multiplyGF256( 0x09) xor a[3].multiplyGF256(0x0e)
//@formatter:on

for (i in 0..3) {
this[i, c] = b[i].toByte()
}
}

return this
}

0 comments on commit bf99bbd

Please sign in to comment.