備忘録

備忘録

KotlinでAES/ZeroPaddingで暗号化と複合する方法

Ⅰ. はじめに

タイトルの通り「KotlinでAES/ZeroPaddingで暗号化と複合する方法」です。

Ⅱ. サンプルプログラム

import org.dom4j.io.SAXReader
import java.io.File
import java.io.FileWriter
import javax.crypto.spec.SecretKeySpec
import javax.crypto.Cipher
import java.util.*
import javax.crypto.spec.IvParameterSpec

fun byteArrayOfInts(vararg ints: Int) = ByteArray(ints.size) { pos -> ints[pos].toByte() }

fun concatByteArray(array1: ByteArray, array2: ByteArray): ByteArray {
  val newArray = ByteArray(array1.size + array2.size)
  System.arraycopy(array1, 0, newArray, 0, array1.size)
  System.arraycopy(array2, 0, newArray, array1.size, array2.size)
  return newArray
}

fun encrypt(key: ByteArray, iv: ByteArray, str: String): String {
  val cipher = Cipher.getInstance("AES/CBC/NoPadding")
  val secretKeySpec = SecretKeySpec(key, "AES")
  val ivParameterSpec = IvParameterSpec(iv)
  cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec)
  var bytes = str.toByteArray()
  if (bytes.size % 16 != 0) {
    val paddingBytes = ByteArray(16 - (bytes.size % 16))
    bytes = concatByteArray(bytes, paddingBytes)
  }

  return Base64.getEncoder().encodeToString(cipher.doFinal(bytes))
}

fun decrypt(key: ByteArray, iv: ByteArray, str: String): String {
  val cipher = Cipher.getInstance("AES/CBC/NoPadding")
  val secretKeySpec = SecretKeySpec(key, "AES")
  val ivParameterSpec = IvParameterSpec(iv)
  cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec)
  var bytes = Base64.getDecoder().decode(str)
  bytes = cipher.doFinal(bytes)

  var paddingCount = 0
  for (i in bytes.size - 1 downTo 0) {
    if (bytes[i].toInt() == 0) {
      paddingCount++
    } else {
      break
    }
  }

  val newArray = ByteArray(bytes.size - paddingCount)
  System.arraycopy(bytes, 0, newArray, 0, bytes.size - paddingCount)
  return String(newArray)
}

fun main(args: Array<String>) {
  val key = "4b865d387f4a434da70d17a258976a9c".toByteArray()
  val iv = byteArrayOfInts(0x2f, 0x15, 0x25, 0x50, 0x51, 0xAD, 0xEB, 0xCB, 0x01, 0x60, 0x16, 0x32, 0x56, 0xBB, 0x12, 0xDD)
  val str = encrypt(key, iv, "Hello World!")
  println("$str")
  println("${decrypt(key, iv, str)}")
}

実行結果

0NmDTGCeDKGbhbQt/ltnaw==
Hello World!