1package main 2 3import ( 4 "bufio" 5 "bytes" 6 "golang.org/x/crypto/cast5" 7 "crypto/cipher" 8 "encoding/hex" 9 "fmt" 10 "os" 11 "strings" 12) 13 14func unhexlify(s string) []byte { 15 bytes, err := hex.DecodeString(s) 16 if err != nil { 17 panic(err) 18 } 19 return bytes 20} 21 22type vectorArgs struct { 23 count string 24 key string 25 iv string 26 plaintext string 27 ciphertext string 28} 29 30type vectorVerifier interface { 31 validate(count string, key, iv, plaintext, expectedCiphertext []byte) 32} 33 34type ofbVerifier struct{} 35 36func (o ofbVerifier) validate(count string, key, iv, plaintext, expectedCiphertext []byte) { 37 block, err := cast5.NewCipher(key) 38 if err != nil { 39 panic(err) 40 } 41 42 ciphertext := make([]byte, len(plaintext)) 43 stream := cipher.NewOFB(block, iv) 44 stream.XORKeyStream(ciphertext, plaintext) 45 46 if !bytes.Equal(ciphertext, expectedCiphertext) { 47 panic(fmt.Errorf("vector mismatch @ COUNT = %s:\n %s != %s\n", 48 count, 49 hex.EncodeToString(expectedCiphertext), 50 hex.EncodeToString(ciphertext))) 51 } 52} 53 54type cbcVerifier struct{} 55 56func (o cbcVerifier) validate(count string, key, iv, plaintext, expectedCiphertext []byte) { 57 block, err := cast5.NewCipher(key) 58 if err != nil { 59 panic(err) 60 } 61 62 ciphertext := make([]byte, len(plaintext)) 63 mode := cipher.NewCBCEncrypter(block, iv) 64 mode.CryptBlocks(ciphertext, plaintext) 65 66 if !bytes.Equal(ciphertext, expectedCiphertext) { 67 panic(fmt.Errorf("vector mismatch @ COUNT = %s:\n %s != %s\n", 68 count, 69 hex.EncodeToString(expectedCiphertext), 70 hex.EncodeToString(ciphertext))) 71 } 72} 73 74type cfbVerifier struct{} 75 76func (o cfbVerifier) validate(count string, key, iv, plaintext, expectedCiphertext []byte) { 77 block, err := cast5.NewCipher(key) 78 if err != nil { 79 panic(err) 80 } 81 82 ciphertext := make([]byte, len(plaintext)) 83 stream := cipher.NewCFBEncrypter(block, iv) 84 stream.XORKeyStream(ciphertext, plaintext) 85 86 if !bytes.Equal(ciphertext, expectedCiphertext) { 87 panic(fmt.Errorf("vector mismatch @ COUNT = %s:\n %s != %s\n", 88 count, 89 hex.EncodeToString(expectedCiphertext), 90 hex.EncodeToString(ciphertext))) 91 } 92} 93 94type ctrVerifier struct{} 95 96func (o ctrVerifier) validate(count string, key, iv, plaintext, expectedCiphertext []byte) { 97 block, err := cast5.NewCipher(key) 98 if err != nil { 99 panic(err) 100 } 101 102 ciphertext := make([]byte, len(plaintext)) 103 stream := cipher.NewCTR(block, iv) 104 stream.XORKeyStream(ciphertext, plaintext) 105 106 if !bytes.Equal(ciphertext, expectedCiphertext) { 107 panic(fmt.Errorf("vector mismatch @ COUNT = %s:\n %s != %s\n", 108 count, 109 hex.EncodeToString(expectedCiphertext), 110 hex.EncodeToString(ciphertext))) 111 } 112} 113 114func validateVectors(verifier vectorVerifier, filename string) { 115 vectors, err := os.Open(filename) 116 if err != nil { 117 panic(err) 118 } 119 defer vectors.Close() 120 121 var segments []string 122 var vector *vectorArgs 123 124 scanner := bufio.NewScanner(vectors) 125 for scanner.Scan() { 126 segments = strings.Split(scanner.Text(), " = ") 127 128 switch { 129 case strings.ToUpper(segments[0]) == "COUNT": 130 if vector != nil { 131 verifier.validate(vector.count, 132 unhexlify(vector.key), 133 unhexlify(vector.iv), 134 unhexlify(vector.plaintext), 135 unhexlify(vector.ciphertext)) 136 } 137 vector = &vectorArgs{count: segments[1]} 138 case strings.ToUpper(segments[0]) == "IV": 139 vector.iv = segments[1][:16] 140 case strings.ToUpper(segments[0]) == "KEY": 141 vector.key = segments[1] 142 case strings.ToUpper(segments[0]) == "PLAINTEXT": 143 vector.plaintext = segments[1] 144 case strings.ToUpper(segments[0]) == "CIPHERTEXT": 145 vector.ciphertext = segments[1] 146 } 147 } 148 149} 150 151func main() { 152 validateVectors(ofbVerifier{}, 153 "vectors/cryptography_vectors/ciphers/CAST5/cast5-ofb.txt") 154 fmt.Println("OFB OK.") 155 validateVectors(cfbVerifier{}, 156 "vectors/cryptography_vectors/ciphers/CAST5/cast5-cfb.txt") 157 fmt.Println("CFB OK.") 158 validateVectors(cbcVerifier{}, 159 "vectors/cryptography_vectors/ciphers/CAST5/cast5-cbc.txt") 160 fmt.Println("CBC OK.") 161 validateVectors(ctrVerifier{}, 162 "vectors/cryptography_vectors/ciphers/CAST5/cast5-ctr.txt") 163 fmt.Println("CTR OK.") 164} 165