112 lines
2.6 KiB
Go
112 lines
2.6 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"crypto/rc4"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
func unhexlify(s string) []byte {
|
|
bytes, err := hex.DecodeString(s)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return bytes
|
|
}
|
|
|
|
type vectorArgs struct {
|
|
count string
|
|
offset uint64
|
|
key string
|
|
plaintext string
|
|
ciphertext string
|
|
}
|
|
|
|
type vectorVerifier interface {
|
|
validate(count string, offset uint64, key, plaintext, expectedCiphertext []byte)
|
|
}
|
|
|
|
type arc4Verifier struct{}
|
|
|
|
func (o arc4Verifier) validate(count string, offset uint64, key, plaintext, expectedCiphertext []byte) {
|
|
if offset%16 != 0 || len(plaintext) != 16 || len(expectedCiphertext) != 16 {
|
|
panic(fmt.Errorf("Unexpected input value encountered: offset=%v; len(plaintext)=%v; len(expectedCiphertext)=%v",
|
|
offset,
|
|
len(plaintext),
|
|
len(expectedCiphertext)))
|
|
}
|
|
stream, err := rc4.NewCipher(key)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
var currentOffset uint64 = 0
|
|
ciphertext := make([]byte, len(plaintext))
|
|
for currentOffset <= offset {
|
|
stream.XORKeyStream(ciphertext, plaintext)
|
|
currentOffset += uint64(len(plaintext))
|
|
}
|
|
if !bytes.Equal(ciphertext, expectedCiphertext) {
|
|
panic(fmt.Errorf("vector mismatch @ COUNT = %s:\n %s != %s\n",
|
|
count,
|
|
hex.EncodeToString(expectedCiphertext),
|
|
hex.EncodeToString(ciphertext)))
|
|
}
|
|
}
|
|
|
|
func validateVectors(verifier vectorVerifier, filename string) {
|
|
vectors, err := os.Open(filename)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer vectors.Close()
|
|
|
|
var segments []string
|
|
var vector *vectorArgs
|
|
|
|
scanner := bufio.NewScanner(vectors)
|
|
for scanner.Scan() {
|
|
segments = strings.Split(scanner.Text(), " = ")
|
|
|
|
switch {
|
|
case strings.ToUpper(segments[0]) == "COUNT":
|
|
if vector != nil {
|
|
verifier.validate(vector.count,
|
|
vector.offset,
|
|
unhexlify(vector.key),
|
|
unhexlify(vector.plaintext),
|
|
unhexlify(vector.ciphertext))
|
|
}
|
|
vector = &vectorArgs{count: segments[1]}
|
|
case strings.ToUpper(segments[0]) == "OFFSET":
|
|
vector.offset, err = strconv.ParseUint(segments[1], 10, 64)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
case strings.ToUpper(segments[0]) == "KEY":
|
|
vector.key = segments[1]
|
|
case strings.ToUpper(segments[0]) == "PLAINTEXT":
|
|
vector.plaintext = segments[1]
|
|
case strings.ToUpper(segments[0]) == "CIPHERTEXT":
|
|
vector.ciphertext = segments[1]
|
|
}
|
|
}
|
|
if vector != nil {
|
|
verifier.validate(vector.count,
|
|
vector.offset,
|
|
unhexlify(vector.key),
|
|
unhexlify(vector.plaintext),
|
|
unhexlify(vector.ciphertext))
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
validateVectors(arc4Verifier{}, "vectors/cryptography_vectors/ciphers/ARC4/arc4.txt")
|
|
fmt.Println("ARC4 OK.")
|
|
}
|