Last active
April 7, 2023 06:15
-
-
Save iseki0/493f7a7ab5f49e829d578f2baa3e1f40 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@file:Suppress("DuplicatedCode", "MemberVisibilityCanBePrivate", "DataClassPrivateConstructor") | |
import kotlinx.serialization.KSerializer | |
import kotlinx.serialization.Serializable | |
import kotlinx.serialization.descriptors.SerialDescriptor | |
import kotlinx.serialization.descriptors.serialDescriptor | |
import kotlinx.serialization.encoding.Decoder | |
import kotlinx.serialization.encoding.Encoder | |
import java.io.File | |
import java.io.InputStream | |
import java.security.MessageDigest | |
import java.util.HexFormat | |
private fun decodeInt(a: ByteArray, off: Int): Int = (a[off * 4].toInt() shl 24) or | |
(a[off * 4 + 1].toInt() and 0xff shl 16) or | |
(a[off * 4 + 2].toInt() and 0xff shl 8) or | |
(a[off * 4 + 3].toInt() and 0xff) | |
private fun encodeInt(a: ByteArray, off: Int, i: Int) { | |
a[off * 4] = (i shr 24).toByte() | |
a[off * 4 + 1] = (i shr 16).toByte() | |
a[off * 4 + 2] = (i shr 8).toByte() | |
a[off * 4 + 3] = i.toByte() | |
} | |
private fun encodeHex(a: ByteArray) = HexFormat.of().formatHex(a)!! | |
private fun decodeHex(s: String) = HexFormat.of().parseHex(s)!! | |
//fun generateTypes(len: Int, name: String): String { | |
// val blen = len * 4 | |
// val fields = (0 until len).joinToString(separator = "\n") { "private val i$it: Int," } | |
// val decodes = (1 until len).joinToString(separator = "\n") { "decodeInt(a, $it)," } | |
// val encodes = (0 until len).joinToString(separator = "\n") { "encodeInt(it, $it, i$it)" } | |
// | |
// return """ | |
// @JvmRecord | |
// @Serializable($name.Serializer::class) | |
// data class $name private constructor( | |
// $fields | |
// ) { | |
// fun toBytes() = ByteArray($blen).also { | |
// $encodes | |
// } | |
// | |
// override fun toString(): String = encodeHex(toBytes()) | |
// | |
// constructor(a: ByteArray) : this( | |
// decodeInt(a, 0).also { require(a.size == $blen) }, | |
// $decodes | |
// ) | |
// | |
// constructor(a: String) : this(decodeHex(a)) | |
// | |
// internal object Serializer : KSerializer<$name> { | |
// override val descriptor: SerialDescriptor = serialDescriptor<String>() | |
// | |
// override fun deserialize(decoder: Decoder): $name = $name(decoder.decodeString()) | |
// | |
// override fun serialize(encoder: Encoder, value: $name) { | |
// encoder.encodeString(value.toString()) | |
// } | |
// | |
// } | |
// } | |
// | |
// """.trimIndent() | |
//} | |
// | |
//fun main() { | |
// generateTypes(4, "MD5").also(::println) | |
// generateTypes(5, "Sha1").also(::println) | |
// generateTypes(7, "Sha224").also(::println) | |
// generateTypes(8, "Sha256").also(::println) | |
// generateTypes(12, "Sha384").also(::println) | |
// generateTypes(16, "Sha512").also(::println) | |
//} | |
@JvmRecord | |
@Serializable(MD5.Serializer::class) | |
data class MD5 private constructor( | |
private val i0: Int, | |
private val i1: Int, | |
private val i2: Int, | |
private val i3: Int, | |
) { | |
fun toBytes() = ByteArray(16).also { | |
encodeInt(it, 0, i0) | |
encodeInt(it, 1, i1) | |
encodeInt(it, 2, i2) | |
encodeInt(it, 3, i3) | |
} | |
override fun toString(): String = encodeHex(toBytes()) | |
constructor(a: ByteArray) : this( | |
decodeInt(a, 0).also { require(a.size == 16) }, | |
decodeInt(a, 1), | |
decodeInt(a, 2), | |
decodeInt(a, 3), | |
) | |
constructor(a: String) : this(decodeHex(a)) | |
internal object Serializer : KSerializer<MD5> { | |
override val descriptor: SerialDescriptor = serialDescriptor<String>() | |
override fun deserialize(decoder: Decoder): MD5 = MD5(decoder.decodeString()) | |
override fun serialize(encoder: Encoder, value: MD5) { | |
encoder.encodeString(value.toString()) | |
} | |
} | |
} | |
@JvmRecord | |
@Serializable(Sha1.Serializer::class) | |
data class Sha1 private constructor( | |
private val i0: Int, | |
private val i1: Int, | |
private val i2: Int, | |
private val i3: Int, | |
private val i4: Int, | |
) { | |
fun toBytes() = ByteArray(20).also { | |
encodeInt(it, 0, i0) | |
encodeInt(it, 1, i1) | |
encodeInt(it, 2, i2) | |
encodeInt(it, 3, i3) | |
encodeInt(it, 4, i4) | |
} | |
override fun toString(): String = encodeHex(toBytes()) | |
constructor(a: ByteArray) : this( | |
decodeInt(a, 0).also { require(a.size == 20) }, | |
decodeInt(a, 1), | |
decodeInt(a, 2), | |
decodeInt(a, 3), | |
decodeInt(a, 4), | |
) | |
constructor(a: String) : this(decodeHex(a)) | |
internal object Serializer : KSerializer<Sha1> { | |
override val descriptor: SerialDescriptor = serialDescriptor<String>() | |
override fun deserialize(decoder: Decoder): Sha1 = Sha1(decoder.decodeString()) | |
override fun serialize(encoder: Encoder, value: Sha1) { | |
encoder.encodeString(value.toString()) | |
} | |
} | |
} | |
@JvmRecord | |
@Serializable(Sha224.Serializer::class) | |
data class Sha224 private constructor( | |
private val i0: Int, | |
private val i1: Int, | |
private val i2: Int, | |
private val i3: Int, | |
private val i4: Int, | |
private val i5: Int, | |
private val i6: Int, | |
) { | |
fun toBytes() = ByteArray(28).also { | |
encodeInt(it, 0, i0) | |
encodeInt(it, 1, i1) | |
encodeInt(it, 2, i2) | |
encodeInt(it, 3, i3) | |
encodeInt(it, 4, i4) | |
encodeInt(it, 5, i5) | |
encodeInt(it, 6, i6) | |
} | |
override fun toString(): String = encodeHex(toBytes()) | |
constructor(a: ByteArray) : this( | |
decodeInt(a, 0).also { require(a.size == 28) }, | |
decodeInt(a, 1), | |
decodeInt(a, 2), | |
decodeInt(a, 3), | |
decodeInt(a, 4), | |
decodeInt(a, 5), | |
decodeInt(a, 6), | |
) | |
constructor(a: String) : this(decodeHex(a)) | |
internal object Serializer : KSerializer<Sha224> { | |
override val descriptor: SerialDescriptor = serialDescriptor<String>() | |
override fun deserialize(decoder: Decoder): Sha224 = Sha224(decoder.decodeString()) | |
override fun serialize(encoder: Encoder, value: Sha224) { | |
encoder.encodeString(value.toString()) | |
} | |
} | |
} | |
@JvmRecord | |
@Serializable(Sha256.Serializer::class) | |
data class Sha256 private constructor( | |
private val i0: Int, | |
private val i1: Int, | |
private val i2: Int, | |
private val i3: Int, | |
private val i4: Int, | |
private val i5: Int, | |
private val i6: Int, | |
private val i7: Int, | |
) { | |
fun toBytes() = ByteArray(32).also { | |
encodeInt(it, 0, i0) | |
encodeInt(it, 1, i1) | |
encodeInt(it, 2, i2) | |
encodeInt(it, 3, i3) | |
encodeInt(it, 4, i4) | |
encodeInt(it, 5, i5) | |
encodeInt(it, 6, i6) | |
encodeInt(it, 7, i7) | |
} | |
override fun toString(): String = encodeHex(toBytes()) | |
constructor(a: ByteArray) : this( | |
decodeInt(a, 0).also { require(a.size == 32) }, | |
decodeInt(a, 1), | |
decodeInt(a, 2), | |
decodeInt(a, 3), | |
decodeInt(a, 4), | |
decodeInt(a, 5), | |
decodeInt(a, 6), | |
decodeInt(a, 7), | |
) | |
constructor(a: String) : this(decodeHex(a)) | |
internal object Serializer : KSerializer<Sha256> { | |
override val descriptor: SerialDescriptor = serialDescriptor<String>() | |
override fun deserialize(decoder: Decoder): Sha256 = Sha256(decoder.decodeString()) | |
override fun serialize(encoder: Encoder, value: Sha256) { | |
encoder.encodeString(value.toString()) | |
} | |
} | |
} | |
@JvmRecord | |
@Serializable(Sha384.Serializer::class) | |
data class Sha384 private constructor( | |
private val i0: Int, | |
private val i1: Int, | |
private val i2: Int, | |
private val i3: Int, | |
private val i4: Int, | |
private val i5: Int, | |
private val i6: Int, | |
private val i7: Int, | |
private val i8: Int, | |
private val i9: Int, | |
private val i10: Int, | |
private val i11: Int, | |
) { | |
fun toBytes() = ByteArray(48).also { | |
encodeInt(it, 0, i0) | |
encodeInt(it, 1, i1) | |
encodeInt(it, 2, i2) | |
encodeInt(it, 3, i3) | |
encodeInt(it, 4, i4) | |
encodeInt(it, 5, i5) | |
encodeInt(it, 6, i6) | |
encodeInt(it, 7, i7) | |
encodeInt(it, 8, i8) | |
encodeInt(it, 9, i9) | |
encodeInt(it, 10, i10) | |
encodeInt(it, 11, i11) | |
} | |
override fun toString(): String = encodeHex(toBytes()) | |
constructor(a: ByteArray) : this( | |
decodeInt(a, 0).also { require(a.size == 48) }, | |
decodeInt(a, 1), | |
decodeInt(a, 2), | |
decodeInt(a, 3), | |
decodeInt(a, 4), | |
decodeInt(a, 5), | |
decodeInt(a, 6), | |
decodeInt(a, 7), | |
decodeInt(a, 8), | |
decodeInt(a, 9), | |
decodeInt(a, 10), | |
decodeInt(a, 11), | |
) | |
constructor(a: String) : this(decodeHex(a)) | |
internal object Serializer : KSerializer<Sha384> { | |
override val descriptor: SerialDescriptor = serialDescriptor<String>() | |
override fun deserialize(decoder: Decoder): Sha384 = Sha384(decoder.decodeString()) | |
override fun serialize(encoder: Encoder, value: Sha384) { | |
encoder.encodeString(value.toString()) | |
} | |
} | |
} | |
@JvmRecord | |
@Serializable(Sha512.Serializer::class) | |
data class Sha512 private constructor( | |
private val i0: Int, | |
private val i1: Int, | |
private val i2: Int, | |
private val i3: Int, | |
private val i4: Int, | |
private val i5: Int, | |
private val i6: Int, | |
private val i7: Int, | |
private val i8: Int, | |
private val i9: Int, | |
private val i10: Int, | |
private val i11: Int, | |
private val i12: Int, | |
private val i13: Int, | |
private val i14: Int, | |
private val i15: Int, | |
) { | |
fun toBytes() = ByteArray(64).also { | |
encodeInt(it, 0, i0) | |
encodeInt(it, 1, i1) | |
encodeInt(it, 2, i2) | |
encodeInt(it, 3, i3) | |
encodeInt(it, 4, i4) | |
encodeInt(it, 5, i5) | |
encodeInt(it, 6, i6) | |
encodeInt(it, 7, i7) | |
encodeInt(it, 8, i8) | |
encodeInt(it, 9, i9) | |
encodeInt(it, 10, i10) | |
encodeInt(it, 11, i11) | |
encodeInt(it, 12, i12) | |
encodeInt(it, 13, i13) | |
encodeInt(it, 14, i14) | |
encodeInt(it, 15, i15) | |
} | |
override fun toString(): String = encodeHex(toBytes()) | |
constructor(a: ByteArray) : this( | |
decodeInt(a, 0).also { require(a.size == 64) }, | |
decodeInt(a, 1), | |
decodeInt(a, 2), | |
decodeInt(a, 3), | |
decodeInt(a, 4), | |
decodeInt(a, 5), | |
decodeInt(a, 6), | |
decodeInt(a, 7), | |
decodeInt(a, 8), | |
decodeInt(a, 9), | |
decodeInt(a, 10), | |
decodeInt(a, 11), | |
decodeInt(a, 12), | |
decodeInt(a, 13), | |
decodeInt(a, 14), | |
decodeInt(a, 15), | |
) | |
constructor(a: String) : this(decodeHex(a)) | |
internal object Serializer : KSerializer<Sha512> { | |
override val descriptor: SerialDescriptor = serialDescriptor<String>() | |
override fun deserialize(decoder: Decoder): Sha512 = Sha512(decoder.decodeString()) | |
override fun serialize(encoder: Encoder, value: Sha512) { | |
encoder.encodeString(value.toString()) | |
} | |
} | |
} | |
internal fun MessageDigest.hashStream(inputStream: InputStream): ByteArray { | |
val buffer = ByteArray(4 * 1024) | |
var read: Int | |
while (inputStream.read(buffer).also { read = it } > -1) { | |
update(buffer, 0, read) | |
} | |
return digest() | |
} | |
private fun getSha256() = MessageDigest.getInstance("SHA-256")!! | |
fun InputStream.sha256() = getSha256().hashStream(this).let(::Sha256) | |
fun File.sha256() = inputStream().use { it.sha256() } | |
fun ByteArray.sha256() = getSha256().digest(this).let(::Sha1) | |
private fun getSha1() = MessageDigest.getInstance("SHA-1")!! | |
fun InputStream.sha1() = getSha1().hashStream(this).let(::Sha1) | |
fun File.sha1() = inputStream().use { it.sha1() } | |
fun ByteArray.sha1() = getSha1().digest(this).let(::Sha1) | |
private fun getMD5() = MessageDigest.getInstance("MD5")!! | |
fun InputStream.md5() = getMD5().hashStream(this).let(::MD5) | |
fun File.md5() = inputStream().use { it.md5() } | |
fun ByteArray.md5() = getMD5().digest(this).let(::MD5) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment