易位密码

Kotlin 易位密码算法

Kotlin 实现易位密码算法

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import java.util.*
import kotlin.collections.HashMap

object Main {

    @JvmStatic
    fun main(args: Array<String>) {
        val key = "aoada"
        val text = "12345"
        val enc = text.encrypt(key)
        println("密钥为 ${key.genKey().joinToString("")}")
        println("明文 -> $text, 加密后 -> ${text.encrypt(key)}")
        println("密文 -> $enc, 解密后 -> ${enc.decrypt(key)}")
    }

    private data class EncryptList(val id: Char, val list: List<Char>)

    private fun String.genKey(): MutableList<Char> {
        val res = LinkedList<Char>()
        this.forEach { el ->
            if (!el.isLetterOrDigit()) {
                throw IllegalArgumentException("密钥必须为数字或字母")
            }
            var t = el.uppercaseChar()
            var digitCount = 0
            var letterCount = 0
            // 如果 密钥队列里已经存在当前字符了,那就对下一个字符进行处理
            // 尝试顺移
            while (res.contains(t)) {
                when {
                    t.isDigit() -> {
                        t += 1
                        digitCount++
                        if (t > '9') {
                            t = '0'
                        }
                        if (digitCount > 10) {
                            throw IllegalArgumentException("密钥中的数字过多!")
                        }
                    }
                    t.isLetter() -> {
                        t += 1
                        letterCount++
                        if (t > 'Z') {
                            t = 'A'
                        }
                        if (letterCount > 26) {
                            throw IllegalArgumentException("密钥中的字母过多!")
                        }
                    }
                }
            }
            res.add(t)
        }
        return res
    }

    private fun String.genPlainText(): MutableList<Char> {
        val res = LinkedList<Char>()
        this.forEach {
            if (it != ' ') {
                res.add(it)
            }
        }
        return res
    }

    private fun List<EncryptList>.genEncrypt(): String {
        val res = StringBuilder()
        this.sortedBy { it.id }.forEach {
            res.append(it.list.joinToString(""))
        }
        return res.toString()
    }

    private fun List<EncryptList>.genDecrypt(key: String): String {
        val res = StringBuilder()
        var column = 0
        val xSize = this.size
        while (column <= xSize) {
            key.genKey().forEach {
                this.forEach { el ->
                    if (it == el.id && el.list.size > column) {
                        res.append(el.list[column])
                    }
                }
            }
            column++
        }
        return res.toString()
    }

    private fun String.encrypt(key: String): String {
        val keyArray = key.genKey()
        val textArray = this.genPlainText()
        val keySize = keyArray.size
        val textSize = textArray.size
        val res = LinkedList<EncryptList>()
        for (i in 0 until keySize) {
            val list = LinkedList<Char>()
            var j = i
            do {
                runCatching {
                    list.add(textArray[j])
                }.onFailure {
                    it.printStackTrace()
                    throw IllegalArgumentException("密钥过长或明文过短,请尝试缩短密钥位数或增加明文长度!")
                }
                j += keySize
            } while (j < textSize)
            res.add(EncryptList(keyArray[i], list))
        }
        return res.genEncrypt()
    }

    private fun String.decrypt(key: String): String {
        val keyArray = key.genKey()
        val textArray = this.genPlainText()
        val keySize = keyArray.size
        val textSize = textArray.size
        val res = LinkedList<EncryptList>()
        var outNum = textSize.mod(keySize)
        val row = textSize.div(keySize)
        val keyMap = HashMap<Char, Int>()
        keyArray.forEach {
            var num = row
            if (outNum > 0) {
                num = row + 1
                outNum--
            }
            keyMap[it] = num
        }
        println(keyMap)
        keyMap.forEach { kMap ->
            val keyPlain = LinkedList<Char>()
            for (i in outNum until outNum + kMap.value) {
                runCatching {
                    keyPlain.add(textArray[i])
                }.onFailure {
                    it.printStackTrace()
                    throw IllegalArgumentException("密钥过长或明文过短,请尝试缩短密钥位数或增加明文长度!")
                }
            }
            outNum += kMap.value
            res.add(EncryptList(kMap.key, keyPlain))
        }
        return res.genDecrypt(key)
    }
}
updatedupdated2021-12-262021-12-26