MengYX
3 years ago
2 changed files with 154 additions and 0 deletions
@ -0,0 +1,69 @@ |
|||||
|
// Copyright 2021 MengYX. All rights reserved.
|
||||
|
//
|
||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
|
// Use of this source code is governed by a BSD-style
|
||||
|
// license that can be found in https://go.dev/LICENSE.
|
||||
|
|
||||
|
import {TeaCipher} from "@/utils/tea"; |
||||
|
|
||||
|
test("key size", () => { |
||||
|
const testKey = new Uint8Array([ |
||||
|
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, |
||||
|
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, |
||||
|
0x00 |
||||
|
]) |
||||
|
expect(() => new TeaCipher(testKey.slice(0, 16))) |
||||
|
.not.toThrow() |
||||
|
|
||||
|
expect(() => new TeaCipher(testKey)) |
||||
|
.toThrow() |
||||
|
|
||||
|
expect(() => new TeaCipher(testKey.slice(0, 15))) |
||||
|
.toThrow() |
||||
|
|
||||
|
}) |
||||
|
|
||||
|
|
||||
|
const teaTests = [ |
||||
|
// These were sourced from https://github.com/froydnj/ironclad/blob/master/testing/test-vectors/tea.testvec
|
||||
|
{ |
||||
|
rounds: TeaCipher.numRounds, |
||||
|
key: new Uint8Array([ |
||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), |
||||
|
plainText: new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), |
||||
|
cipherText: new Uint8Array([0x41, 0xea, 0x3a, 0x0a, 0x94, 0xba, 0xa9, 0x40]), |
||||
|
}, |
||||
|
{ |
||||
|
rounds: TeaCipher.numRounds, |
||||
|
key: new Uint8Array([ |
||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), |
||||
|
plainText: new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), |
||||
|
cipherText: new Uint8Array([0x31, 0x9b, 0xbe, 0xfb, 0x01, 0x6a, 0xbd, 0xb2]), |
||||
|
}, |
||||
|
{ |
||||
|
rounds: 16, |
||||
|
key: new Uint8Array([ |
||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), |
||||
|
plainText: new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), |
||||
|
cipherText: new Uint8Array([0xed, 0x28, 0x5d, 0xa1, 0x45, 0x5b, 0x33, 0xc1]), |
||||
|
}, |
||||
|
] |
||||
|
|
||||
|
|
||||
|
test("encrypt & decrypt", () => { |
||||
|
for (const tt of teaTests) { |
||||
|
const c = new TeaCipher(tt.key, tt.rounds) |
||||
|
|
||||
|
const buf = new Uint8Array(8) |
||||
|
const bufView = new DataView(buf.buffer) |
||||
|
|
||||
|
c.encrypt(bufView, new DataView(tt.plainText.buffer)) |
||||
|
expect(buf).toStrictEqual(tt.cipherText) |
||||
|
|
||||
|
c.decrypt(bufView, new DataView(tt.cipherText.buffer)) |
||||
|
expect(buf).toStrictEqual(tt.plainText) |
||||
|
} |
||||
|
}) |
@ -0,0 +1,85 @@ |
|||||
|
// Copyright 2021 MengYX. All rights reserved.
|
||||
|
//
|
||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
|
// Use of this source code is governed by a BSD-style
|
||||
|
// license that can be found in https://go.dev/LICENSE.
|
||||
|
|
||||
|
// TeaCipher is a typescript port to golang.org/x/crypto/tea
|
||||
|
|
||||
|
// Package tea implements the TEA algorithm, as defined in Needham and
|
||||
|
// Wheeler's 1994 technical report, “TEA, a Tiny Encryption Algorithm”. See
|
||||
|
// http://www.cix.co.uk/~klockstone/tea.pdf for details.
|
||||
|
//
|
||||
|
// TEA is a legacy cipher and its short block size makes it vulnerable to
|
||||
|
// birthday bound attacks (see https://sweet32.info). It should only be used
|
||||
|
// where compatibility with legacy systems, not security, is the goal.
|
||||
|
|
||||
|
export class TeaCipher { |
||||
|
// BlockSize is the size of a TEA block, in bytes.
|
||||
|
static readonly BlockSize = 8; |
||||
|
|
||||
|
// KeySize is the size of a TEA key, in bytes.
|
||||
|
static readonly KeySize = 16; |
||||
|
|
||||
|
// delta is the TEA key schedule constant.
|
||||
|
static readonly delta = 0x9e3779b9; |
||||
|
|
||||
|
// numRounds 64 is the standard number of rounds in TEA.
|
||||
|
static readonly numRounds = 64; |
||||
|
|
||||
|
k0: number |
||||
|
k1: number |
||||
|
k2: number |
||||
|
k3: number |
||||
|
rounds: number |
||||
|
|
||||
|
constructor(key: Uint8Array, rounds: number = TeaCipher.numRounds) { |
||||
|
if (key.length != 16) { |
||||
|
throw Error("incorrect key size") |
||||
|
} |
||||
|
if ((rounds & 1) != 0) { |
||||
|
throw Error("odd number of rounds specified") |
||||
|
} |
||||
|
|
||||
|
const k = new DataView(key.buffer) |
||||
|
this.k0 = k.getUint32(0, false) |
||||
|
this.k1 = k.getUint32(4, false) |
||||
|
this.k2 = k.getUint32(8, false) |
||||
|
this.k3 = k.getUint32(12, false) |
||||
|
this.rounds = rounds |
||||
|
} |
||||
|
|
||||
|
|
||||
|
encrypt(dst: DataView, src: DataView) { |
||||
|
if (src.byteLength != 8) { |
||||
|
throw Error("src.byteLength != 8") |
||||
|
} |
||||
|
|
||||
|
let v0 = src.getUint32(0, false) |
||||
|
let v1 = src.getUint32(4, false) |
||||
|
|
||||
|
let sum = 0 |
||||
|
for (let i = 0; i < this.rounds / 2; i++) { |
||||
|
sum = sum + TeaCipher.delta |
||||
|
v0 += ((v1 << 4) + this.k0) ^ (v1 + sum) ^ ((v1 >>> 5) + this.k1) |
||||
|
v1 += ((v0 << 4) + this.k2) ^ (v0 + sum) ^ ((v0 >>> 5) + this.k3) |
||||
|
} |
||||
|
|
||||
|
dst.setUint32(0, v0, false) |
||||
|
dst.setUint32(4, v1, false) |
||||
|
} |
||||
|
|
||||
|
decrypt(dst: DataView, src: DataView) { |
||||
|
let v0 = src.getUint32(0, false) |
||||
|
let v1 = src.getUint32(4, false) |
||||
|
|
||||
|
let sum = TeaCipher.delta * this.rounds / 2 |
||||
|
for (let i = 0; i < this.rounds / 2; i++) { |
||||
|
v1 -= ((v0 << 4) + this.k2) ^ (v0 + sum) ^ ((v0 >>> 5) + this.k3) |
||||
|
v0 -= ((v1 << 4) + this.k0) ^ (v1 + sum) ^ ((v1 >>> 5) + this.k1) |
||||
|
sum -= TeaCipher.delta |
||||
|
} |
||||
|
dst.setUint32(0, v0, false) |
||||
|
dst.setUint32(4, v1, false) |
||||
|
} |
||||
|
} |
Loading…
Reference in new issue