LoginSignup
17
13

More than 5 years have passed since last update.

kotlinで暗号化、復号化

Posted at

暗号化

秘密鍵の生成

SecretKeySpecクラスを使用して秘密鍵を作成します。

val key = SecretKeySpec(["鍵として使用するbyte配列"], "AES")
// ex) val key = SecretKeySpec("0123456789ABCDEF".toByteArray(), "AES")

Cipherクラスのオブジェクトを作成

Cipher.getInstanceで暗号化アルゴリズムを指定してCipherクラスのオブジェクトを作成します。
引数には 暗号化アルゴリズム/動作モード/パディング の書式で指定します。
詳しくは各ドキュメントを参照してください。
developer.android.com
docs.oracle.com

val cipher = Cipher.getInstance("algorithm/mode/padding")
// ex) val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")

秘密鍵の初期化

Cipher.initでCipher.ENCRYPT_MODEを指定して秘密鍵を初期化します。

cipher.init(Cipher.ENCRYPT_MODE, key)

読み込みと書き出し

暗号化したいファイルの読み込んで暗号化し、そのデータを書き出します。

val fis = FileInputStream("./before.json")
val fos = FileOutputStream("./encrypto.byte")
val cos = CipherOutputStream(fos, cipher)
val a = ByteArray(8)
var i = fis.read(a)
while (i != -1) {
  cos.write(a, 0, i)
  i = fis.read(a)
}
cos.flush()
cos.close()

IVをつける

今回はモードをCBCに指定したので、暗号化する際にIV(initialization vector)というものが自動的に作られ使われます。
このIVは復号化の際に必要となるため、暗号化したデータの先頭にIVをつけます。

fos.write(cipher.getIV())

ソースコード全文

encrypto.kt

import java.io.FileInputStream
import java.io.FileOutputStream

import javax.crypto.Cipher
import javax.crypto.CipherInputStream
import javax.crypto.CipherOutputStream
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec


fun main(args: Array<String>) {
  val fis = FileInputStream("./before.json")
  val key = SecretKeySpec("0123456789ABCDEF".toByteArray(), "AES")
  val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
  cipher.init(Cipher.ENCRYPT_MODE, key)
  val fos = FileOutputStream("./encrypto.byte")
  val cos = CipherOutputStream(fos, cipher)
  fos.write(cipher.getIV())
  val a = ByteArray(8)
  var i = fis.read(a)
  while (i != -1) {
    cos.write(a, 0, i)
    i = fis.read(a)
  }
  cos.flush()
  cos.close()
}

復号化

秘密鍵の生成

SecretKeySpecクラスを使用して秘密鍵を作成します。

val key = SecretKeySpec(["鍵として使用するbyte配列"], "AES")
// ex) val key = SecretKeySpec("0123456789ABCDEF".toByteArray(), "AES")

Cipherクラスのオブジェクトを作成

Cipher.getInstanceで暗号化アルゴリズムを指定してCipherクラスのオブジェクトを作成します。
引数には 暗号化アルゴリズム/動作モード/パディング の書式で指定します。

val cipher = Cipher.getInstance("algorithm/mode/padding")
// ex) val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")

IVの読み込み

IV用のbyte配列を用意して、ファイルのIV部分(先頭16byte)を格納します。

val iv = ByteArray(16)
fis.read(iv)

IvParameterSpecの生成

読み込んだIVからIvParameterSpecを生成します。

val ivspec = IvParameterSpec(iv)

秘密鍵の初期化

Cipher.initでCipher.DECRYPT_MODEを指定して秘密鍵を初期化します。
暗号化のときとは異なり、第三引数にIvParameterSpecを指定します。

cipher.init(Cipher.DECRYPT_MODE, key, ivspec)

読み込みと書き出し

ファイルを読み込んで復号化して、そのデータを書き出します。

val fis = FileInputStream("./encrypto.byte")
val cis = CipherInputStream(fis, cipher)
val reader = cis.bufferedReader()
val file = File("./after.json")
val fw = FileWriter(file)
var line: String? = reader.readLine()
while (line != null) {
  fw.write(line)
  line = reader.readLine()
}
reader.close()
fw.close()

ソースコード全文

decrypto.kt
import java.io.FileInputStream
import java.io.File
import java.io.FileWriter

import javax.crypto.Cipher
import javax.crypto.CipherInputStream
import javax.crypto.CipherOutputStream
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec


fun main(args: Array<String>) {
  val fis = FileInputStream("./encrypto.byte")
  val key = SecretKeySpec("0123456789ABCDEF".toByteArray(), "AES")
  val iv = ByteArray(16)
  fis.read(iv)
  val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
  val ivspec = IvParameterSpec(iv)
  cipher.init(Cipher.DECRYPT_MODE, key, ivspec)
  val cis = CipherInputStream(fis, cipher)
  val reader = cis.bufferedReader()

  val file = File("./after.json")
  val fw = FileWriter(file)
  var line: String? = reader.readLine()
  while (line != null) {
    fw.write(line)
    line = reader.readLine()
  }
  reader.close()
  fw.close()
}

コマンドラインでの実行

コンパイル

encripto.kt、decrypto.ktをそれぞれkotlincコマンドでコンパイルしてjarファイルを作成します。

kotlinc encrypto.kt -include-runtime -d encrypto.jar

実行

kotlinコマンドもしくはjavaコマンドで作成したjarファイルを実行します。

kotlin encrypto.jar 
java -jar encrypto.jar
17
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
13