明文:普通字符串
秘钥:普通字符串
密文: 十六进制字符串
以类的形式设计
使用请注意是否有TypeScript开发环境
export namespace UserLib{
export class Des {
private pc1_table = [
57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4,
]
private pc2_table = [
14, 17, 11, 24, 1, 5,
3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8,
16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55,
30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53,
46, 42, 50, 36, 29, 32
]
private rotation_table = [
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1,
]
private ip_table = [
58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6,
64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1,
59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7
]
private ip_inverse_table = [
40, 8, 48, 16, 56, 24, 64, 32,
39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30,
37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28,
35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26,
33, 1, 41, 9, 49, 17, 57, 25,
]
private e_table = [
32, 1, 2, 3, 4, 5,
4, 5, 6, 7, 8, 9,
8, 9, 10, 11, 12, 13,
12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21,
20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29,
28, 29, 30, 31, 32, 1
]
private s_table = [
[
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
],
[
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 10, 5, 14, 9
],
[
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
],
[
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
],
[
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
],
[
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
],
[
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
],
[
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
]
]
private p_table = [
16, 7, 20, 21, 29, 12, 28, 17,
1, 15, 23, 26, 5, 18, 31, 10,
2, 8, 24, 14, 32, 27, 3, 9,
19, 13, 30, 6, 22, 11, 4, 25
]
private pc1_replace(key:string) {
if (key == null) {
return null
}
let result = ""
for (let i in this.pc1_table) {
result += key.charAt(this.pc1_table[i] - 1)
}
return result
}
private pc2_replace(subKeys:string[]) {
if (subKeys == null) {
return null
}
let result: string[] = []
for (let i = 0; i < subKeys.length; i++) {
let temp = ""
// pc2置换
for (let j in this.pc2_table) {
temp += String(subKeys[i]).charAt(this.pc2_table[j] - 1)
}
result.push(temp + '\n')
}
return result
}
private create_16subkeys(compressedKey:string): string[] | null {
if (compressedKey == null) {
return null
}
let C_temp: any = compressedKey.substr(0, 28)
let D_temp: any = compressedKey.substr(28, 28)
let result: string[] = []
for (let i = 0; i < this.rotation_table.length; i++) {
C_temp = BitTool.left_move(C_temp, this.rotation_table[i])
D_temp = BitTool.left_move(D_temp, this.rotation_table[i])
result.push(C_temp + D_temp)
}
return result
}
private ip_replace(text:string) {
if (text == null) {
return null
}
let result = ""
for (let i in this.ip_table) {
result += text.charAt(this.ip_table[i] - 1)
}
return result
}
private ip_inverse_replace(text:string) {
if (text == null) {
return null
}
let result = ""
for (let i in this.ip_inverse_table) {
result += text.charAt(this.ip_inverse_table[i] - 1)
}
return result
}
private f(R: string, K: string) {
let E_R = this.e(R)
let temp = BitTool.xor(E_R, K)
// 进行s盒替换
return this.s(temp)
}
private e(text: string) {
if (text.length !== 32) {
throw new Error("e函数的参数长度不为32位")
}
let result = ""
for (let i in this.e_table) {
result += text.charAt(this.e_table[i] - 1)
}
return result
}
private s(text: string) {
let table = BitTool.divise(text, 6)
let result = ""
for (let i = 0; i < this.s_table.length; i++) {
let row: any = table[i].charAt(0) + table[i].charAt(5)
let column: any = table[i].substr(1, 4)
row = parseInt(row, 2)
column = parseInt(column, 2)
let temp: string|number = this.s_table[i][row * 16 + column]
temp = BitTool.decimal_to_binary(temp)
result += temp
}
let p_temp = ""
for (let i in this.p_table) {
p_temp += result.charAt(this.p_table[i] - 1)
}
return p_temp
}
encode(text:string, key: string) {
if (text === null || key === null) {
return "文本或密钥为空"
}
// 字符串,转化成asc码 * 8
if (text.length < 8 || key.length < 8) {
return "长度不足64位"
}
let binaryKey = BitTool.to_8binary(key)
// 压缩64位密钥到56位
//console.log(`秘钥为:${key} = ${binaryKey}, 长度为:${binaryKey.length}`)
let compressedKey = this.pc1_replace(binaryKey) as string
// 生成16个56位子密钥
let subKeyTable = this.create_16subkeys(compressedKey) as string[]
// 通过pc2置换生成16个48位子密钥
let subKeyCompressTable = this.pc2_replace(subKeyTable) as string[]
//将明文转化成ascii码
let binaryText = BitTool.to_8binary(text)
//console.log(`明文为: ${text} = ${binaryText}`)
let textTable = BitTool.divise(binaryText, 64)
//console.log(`将明文分成${textTable.length}组`)
let result = []
for (let i = 0; i< textTable.length; i++) {
if(textTable[i].length < 64)
textTable[i] = textTable[i].padEnd(64, '0')
//console.log(`第${i + 1}组原文: ${textTable[i]}`)
// ip置换后的明文
let ipText = this.ip_replace(textTable[i])
//console.log(`第${i + 1}组IP置换: ${ipText}`)
let L0 = ipText.substr(0, 32)
let R0 = ipText.substr(32, 32)
// 16轮子密钥变化
for (let i = 0; i < subKeyCompressTable.length; i++) {
let K = subKeyCompressTable[i]
let temp = L0
L0 = R0
let F = this.f(R0, K)
R0 = BitTool.xor(temp, F)
}
// 16轮加密后的结果倒过来
let R0L0 = R0 + L0
//console.log(`第${i + 1}组16轮加密: ${R0L0}`)
R0L0 = this.ip_inverse_replace(R0L0)
//console.log(`第${i + 1}组逆IP置换: ${R0L0}`)
result.push(BitTool.to_Hex(R0L0))
}
return result.toString()
}
decode(cipher:string, key: string) {
if (cipher === null || key === null) {
return "长度不足64位"
}
// 十六进制文本,故64位时长度为16
if (cipher.length < 16 || key.length < 8) {
return "长度不足64位"
}
let binaryKey = BitTool.to_8binary(key)
// 压缩64位密钥到56位
let compressedKey = this.pc1_replace(binaryKey) as string
// 生成16个56位子密钥
let subKeyTable = this.create_16subkeys(compressedKey) as string[]
// 通过pc2置换生成16个48位子密钥
let subKeyCompressTable = this.pc2_replace(subKeyTable) as string[]
let binaryText = BitTool.to_4binary(cipher) as string
// ip置换后的明文
let ipText = this.ip_replace(binaryText) as string
let L0 = ipText.substr(0, 32)
let R0 = ipText.substr(32, 32)
// 16轮子密钥变化
for (let i = 0; i < subKeyCompressTable.length; i++) {
let K = subKeyCompressTable[15 - i]
let temp = L0
L0 = R0
let F = this.f(R0, K)
R0 = BitTool.xor(temp, F)
}
// 16轮加密后的结果倒过来
let R0L0 = R0 + L0
let result = this.ip_inverse_replace(R0L0)
let deal = BitTool.divise(result, 8)
result = ''
for (const d of deal) {
result += String.fromCharCode(parseInt(d, 2))
}
return result
}
}
export class BitTool{
// 将字符串每个十六进制字符转化为二进制表示
static to_4binary(text: string) {
if (text == null) {
return null
}
let binary = ""
for (let i = 0; i < text.length; i++) {
let charCode = parseInt(text.charAt(i), 16).toString(2)
binary += charCode.padStart(4, '0')
}
return binary
}
// 将字符串每个字符转化为ASCII码表示
static to_8binary(text: string) {
if (text == null) {
return null
}
let binary = ""
for (let i = 0; i < text.length; i++) {
let charCode = text.charCodeAt(i)
if (charCode > 255) {
throw new SyntaxError
}
binary += charCode.toString(2).padStart(8, '0')
}
return binary
}
// 二进制字符串到十六进制字符串
static to_Hex(text: string) {
if (text == null) {
return null
}
const asciiTable = BitTool.divise(text, 4)
let binary = ""
for (let i = 0; i < asciiTable.length; i++) {
let hex = parseInt(asciiTable[i], 2).toString(16)
binary += hex
}
return binary
}
//字符串左移
static left_move(text:string, number: number) {
if (text == null) {
return null
}
let result = ""
for (let i = number; i < text.length; i++) {
result += text.charAt(i)
}
for (let i = 0; i < number; i++) {
result += text.charAt(i)
}
return result
}
static xor(x:string, y:string) {
let result = ""
for (let i = 0; i < x.length; i++) {
if (String(x).charAt(i) === String(y).charAt(i)) {
result += "0"
} else {
result += "1"
}
}
return result
}
static divise(text:string, number: number) {
let result:string[] = []
let temp = ""
for (let i = 0; i < text.length; i++) {
if (i !== 0 && i % number === 0) {
result.push(temp)
temp = ""
}
temp += text[i]
}
result.push(temp)
return result
}
static decimal_to_binary(hex: number) {
let charCode = hex.toString(2)
return charCode.padStart(4, '0')
}
}
}
参考了某位大佬的代码
做了小小的改进