Skip to content

Instantly share code, notes, and snippets.

@chimerast
Created June 15, 2021 09:53
Show Gist options
  • Save chimerast/e0608f31f633bb1a8ed9867c21a79f87 to your computer and use it in GitHub Desktop.
Save chimerast/e0608f31f633bb1a8ed9867c21a79f87 to your computer and use it in GitHub Desktop.
KotlinでPEM形式の公開鍵暗号ペアファイルを扱う
/*
このコードはKotlinでPEM形式のRSAおよびEC公開鍵暗号を利用したサンプルプログラムです。
**警告**: 文字列になっている公開暗号鍵ペアは絶対にそのまま使用しないこと。
opensslコマンドを打って必ず自分で生成してください。
実行結果:
[RSA/ECB/PKCS1Padding] matched: true, original: Hello world!, decrypted: Hello world!
[SHA256withRSA] valid: true, original: Hello world!
[SHA256withECDSA] valid: true, original: Hello world!
*/
import com.google.api.client.util.PemReader
import java.io.StringReader
import java.security.KeyFactory
import java.security.PrivateKey
import java.security.PublicKey
import java.security.Signature
import java.security.spec.PKCS8EncodedKeySpec
import java.security.spec.X509EncodedKeySpec
import javax.crypto.Cipher
fun main() {
CryptoSample.rsa("Hello world!")
CryptoSample.ecdsa("Hello world!")
}
object CryptoSample {
fun rsa(plaintext: String) {
/*
openssl genrsa -out key_rsa.pem 2048
openssl rsa -in key_rsa.pem -pubout -out key_rsa.pub
openssl pkcs8 -in key_rsa.pem -topk8 -nocrypt -out key_rsa.key
*/
val rsaPrivateKey = """
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDysAt+YD1mJksi
GW2z9EC1u4bYGvMOCK7lbmQNqEEInAwzxf1mBFlI3Gxz7twXvTjqF7EUaZg2Ue+f
VZ+WbX9ivvJpQrAEUwzbg1H83dso+VYeQNB04MQUpSrfRe1bfNyo6TzKSBr1merc
pKVZxayCNur1VmGsLpzUGaenbH5EcwlSd18sMsioA0opBHZg2WwKjfRwLbTAocr5
qXR/9LgtmjbydxyVX8KSOl2cCLI/t+/xFP9WGl8iZdyQ5OjAmZEI6L/gLWe99RA0
nIrPqT28I5y2ZhxTLYzVXOCRTWhibl4o4Bq0YjUk8JxMPET/o6uNxzcLpZgKOwIg
LyOWLTLDAgMBAAECggEBAIosIw8bujlregF7GtOHMESH9Tka9uE5nmIwHLUN46EE
P4pGooQv26m5HeJPz22QpVPak0585FWhBt3fwRHDW/CbqKa3ekGsCzj7pnVi1wGY
HCjzW/v/cIQUmbkvNfmNuJBO4vaEYR0OOgLPlvjqq9IjdFikis2eaFn2FVckVSug
e4xc3pRjsdUUuP/Y1I8N5rhLdw041DOLQjx7HouTH6KYsQudp5Zn9noR8fOwJ/+z
wZ7hJNqAuvVgmK77imeqUb+J/wABGU+3wSKCLST7A4iqfQWSpwXLcyteUOCs9LK8
MA/g+0L6PwUisqTEfORfqAL4batZrhVdaamr8+RHRCECgYEA+qRC2eHgKnFewV/3
IIVVeBKybp3t0wP7VhbG9LMo3qoMo9C9i1X1zQuf84rQ5pXg6Jo3Rqw8W01KBHPm
NML67I9nz3pCzyffE0lseIy7SKp3y8RFm4BINwUgVlnbDD+AFOIIxlRnqV2ldWBH
GEt+p3312WGhomOT7uhnh9WnkZECgYEA9+BAneYFipfGdfgLHdUTp9otE10GfpZ5
HxQ7jaI0ytAcgMbaxct2FUOVTYWLHcE8u20alETdPk6XLorrHNSUbj9ItB5QyWOT
XVw7e71R1Z72xgCVx20R/jABEXAOliBw6zTtVNr/ZYwLgVMHHj+vK7aflfdNBmQn
UYVdfMDElRMCgYAWwV8IZQdzEwPlTo8jNrfBxQDKJjB3Xf8tm7fIc5OcU5f+L29l
/RHp4cpN1CaPKMBYndey5OQ97dBwgw09cQ5S99oW7iSuphIMsDfW4gAG4uMpbtJb
AdSMmjyLWnEWtZUtUDA3wWX/7G6fL3SE8iW3kyoE6GZCVgQSRqtPm8gw4QKBgGoq
zMJUkS8JTuGcOfavGtob4o6Wm3+Ap6QeIFvLi90KQgsOIQny2ULGTZ6Egk9eQsrs
MiQrUq+rLamrqoQQsPp/dH5hNazsT2P/ayLWtcRPb9bizUQ7fSdoHC0B192JS5QS
eUyM+DLgRtU/YJ8eG8MXV0b+QylnoEeUXbRfRFOtAoGBAKo2t8kVJK1n8pmvF8xR
o+7p4neCm9vVDcX3JSE2me0mlb4ZmN/lGpFcYB/cSqLHoHwhrG4Tu4IBULtdeLwB
36lvr7PMP8jpCHqND9Ilu/OqlmzKKEWMliTk0v68qF3abY63ORBXdhrV8RBWuCV5
DhyGV1iLEJ6hLkK6dU1CLG/D
-----END PRIVATE KEY-----
""".trimIndent()
val rsaPublicKey = """
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8rALfmA9ZiZLIhlts/RA
tbuG2BrzDgiu5W5kDahBCJwMM8X9ZgRZSNxsc+7cF7046hexFGmYNlHvn1Wflm1/
Yr7yaUKwBFMM24NR/N3bKPlWHkDQdODEFKUq30XtW3zcqOk8ykga9Znq3KSlWcWs
gjbq9VZhrC6c1Bmnp2x+RHMJUndfLDLIqANKKQR2YNlsCo30cC20wKHK+al0f/S4
LZo28ncclV/CkjpdnAiyP7fv8RT/VhpfImXckOTowJmRCOi/4C1nvfUQNJyKz6k9
vCOctmYcUy2M1VzgkU1oYm5eKOAatGI1JPCcTDxE/6Orjcc3C6WYCjsCIC8jli0y
wwIDAQAB
-----END PUBLIC KEY-----
""".trimIndent()
val privateKey = KeyFactory.getInstance("RSA").generatePrivate(rsaPrivateKey.fromPKCS8toKeySpec())
val publicKey = KeyFactory.getInstance("RSA").generatePublic(rsaPublicKey.fromX509toKeySpec())
encrypt(plaintext, "RSA/ECB/PKCS1Padding", privateKey, publicKey)
sign(plaintext, "SHA256withRSA", privateKey, publicKey)
}
fun ecdsa(plaintext: String) {
/*
openssl ecparam -genkey -name secp256k1 -out key_ec.pem
openssl ec -in key_ec.pem -pubout -out key_ec.pub
openssl pkcs8 -in key_ec.pem -topk8 -nocrypt -out key_ec.key
*/
val ecPrivateKey = """
-----BEGIN PRIVATE KEY-----
MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQg5jv2Fxm1CgQZv9cvRZd2
hJ1a1hpD3h6lb9GZFwP92ImhRANCAATf48q1i04YGm9+cHj+oUwqYQslXzA7z7io
wlN1BoM+VRzBw2oK4azoM35vGt75C/MERC+hY9cMWjnLtpo2a6rO
-----END PRIVATE KEY-----
""".trimIndent()
val ecPublicKey = """
-----BEGIN PUBLIC KEY-----
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE3+PKtYtOGBpvfnB4/qFMKmELJV8wO8+4
qMJTdQaDPlUcwcNqCuGs6DN+bxre+QvzBEQvoWPXDFo5y7aaNmuqzg==
-----END PUBLIC KEY-----
""".trimIndent()
val privateKey = KeyFactory.getInstance("EC").generatePrivate(ecPrivateKey.fromPKCS8toKeySpec())
val publicKey = KeyFactory.getInstance("EC").generatePublic(ecPublicKey.fromX509toKeySpec())
sign(plaintext, "SHA256withECDSA", privateKey, publicKey)
}
private fun encrypt(plaintext: String, transformation: String, privateKey: PrivateKey, publicKey: PublicKey) {
val encrypt = Cipher.getInstance(transformation)
encrypt.init(Cipher.ENCRYPT_MODE, privateKey)
val ciphertext = encrypt.doFinal(plaintext.toByteArray())
val decrypt = Cipher.getInstance(transformation)
decrypt.init(Cipher.DECRYPT_MODE, publicKey)
val decryptedPlaintext = String(decrypt.doFinal(ciphertext))
println("[$transformation] matched: ${plaintext == decryptedPlaintext}, original: $plaintext, decrypted: $decryptedPlaintext")
}
private fun sign(plaintext: String, transformation: String, privateKey: PrivateKey, publicKey: PublicKey) {
val sign = Signature.getInstance(transformation)
sign.initSign(privateKey)
sign.update(plaintext.toByteArray())
val signature = sign.sign()
val verify = Signature.getInstance(transformation)
verify.initVerify(publicKey)
verify.update(plaintext.toByteArray())
val valid = verify.verify(signature)
println("[$transformation] valid: $valid, original: $plaintext")
}
private fun String.fromPKCS8toKeySpec(): PKCS8EncodedKeySpec {
return PKCS8EncodedKeySpec(PemReader.readFirstSectionAndClose(StringReader(this)).base64DecodedBytes)
}
private fun String.fromX509toKeySpec(): X509EncodedKeySpec {
return X509EncodedKeySpec(PemReader.readFirstSectionAndClose(StringReader(this)).base64DecodedBytes)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment