package main import ( "bufio" "bytes" "code.google.com/p/go.crypto/cast5" "crypto/cipher" "encoding/hex" "fmt" "os" "strings" ) func unhexlify(s string) []byte { bytes, err := hex.DecodeString(s) if err != nil { panic(err) } return bytes } type VectorArgs struct { count string key string iv string plaintext string ciphertext string } type VectorVerifier interface { validate(count string, key, iv, plaintext, expected_ciphertext []byte) } type ofbVerifier struct{} func (o ofbVerifier) validate(count string, key, iv, plaintext, expected_ciphertext []byte) { block, err := cast5.NewCipher(key) if err != nil { panic(err) } ciphertext := make([]byte, len(plaintext)) stream := cipher.NewOFB(block, iv) stream.XORKeyStream(ciphertext, plaintext) if !bytes.Equal(ciphertext, expected_ciphertext) { panic(fmt.Errorf("vector mismatch @ COUNT = %s:\n %s != %s\n", count, hex.EncodeToString(expected_ciphertext), hex.EncodeToString(ciphertext))) } } type cbcVerifier struct{} func (o cbcVerifier) validate(count string, key, iv, plaintext, expected_ciphertext []byte) { block, err := cast5.NewCipher(key) if err != nil { panic(err) } ciphertext := make([]byte, len(plaintext)) mode := cipher.NewCBCEncrypter(block, iv) mode.CryptBlocks(ciphertext, plaintext) if !bytes.Equal(ciphertext, expected_ciphertext) { panic(fmt.Errorf("vector mismatch @ COUNT = %s:\n %s != %s\n", count, hex.EncodeToString(expected_ciphertext), hex.EncodeToString(ciphertext))) } } type cfbVerifier struct{} func (o cfbVerifier) validate(count string, key, iv, plaintext, expected_ciphertext []byte) { block, err := cast5.NewCipher(key) if err != nil { panic(err) } ciphertext := make([]byte, len(plaintext)) stream := cipher.NewCFBEncrypter(block, iv) stream.XORKeyStream(ciphertext, plaintext) if !bytes.Equal(ciphertext, expected_ciphertext) { panic(fmt.Errorf("vector mismatch @ COUNT = %s:\n %s != %s\n", count, hex.EncodeToString(expected_ciphertext), hex.EncodeToString(ciphertext))) } } type ctrVerifier struct{} func (o ctrVerifier) validate(count string, key, iv, plaintext, expected_ciphertext []byte) { block, err := cast5.NewCipher(key) if err != nil { panic(err) } ciphertext := make([]byte, len(plaintext)) stream := cipher.NewCTR(block, iv) stream.XORKeyStream(ciphertext, plaintext) if !bytes.Equal(ciphertext, expected_ciphertext) { panic(fmt.Errorf("vector mismatch @ COUNT = %s:\n %s != %s\n", count, hex.EncodeToString(expected_ciphertext), 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, unhexlify(vector.key), unhexlify(vector.iv), unhexlify(vector.plaintext), unhexlify(vector.ciphertext)) } vector = &VectorArgs{count: segments[1]} case strings.ToUpper(segments[0]) == "IV": vector.iv = segments[1][:16] 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] } } } func main() { validateVectors(ofbVerifier{}, "tests/hazmat/primitives/vectors/ciphers/CAST5/cast5-ofb.txt") fmt.Println("OFB OK.") validateVectors(cfbVerifier{}, "tests/hazmat/primitives/vectors/ciphers/CAST5/cast5-cfb.txt") fmt.Println("CFB OK.") validateVectors(cbcVerifier{}, "tests/hazmat/primitives/vectors/ciphers/CAST5/cast5-cbc.txt") fmt.Println("CBC OK.") validateVectors(ctrVerifier{}, "tests/hazmat/primitives/vectors/ciphers/CAST5/cast5-ctr.txt") fmt.Println("CTR OK.") } QLclWM4IKb-fmh[M[3TQiIFKDDQIAt")FhliChQ4IWZIȭ64d`50miL֛U5VҖ]ޯ8hmABF!3fD*_;k_ܢ23cI%kSMզiRm&5I~^KZ$j+%ZҦehMY f,M0I%#&Pa0ɰ#III 2E055,Mjƫ76)21u]$mZJo.L$jI+)(d&tIYJgQD_y#djrطۛ%JZ(Q_d",Y-;.U4M0ܲJz (뺻aP`^yu"ul$SDܤwtێ pɅo}#QI*Ei.Xs)}w1G䋗ߌJsh`y˓+ :;*scOL[y'B_GM*I }ϸQ(TU+Xp|bO`}?X,@c B%5*ƈ@PX6ۜm: (~ճtJLtM)kLՍ6,mR%Ia2T*Yfuikk !ubiM jLlRAi LFm%)%IbƍRQ0%dTU+LdJ"&YfElE11y+U(,E2!C?ؽI~xcf5X5^E2R&b5"k",cjdRb%=Wmф6_Z2ҵ (j)bLlE2f2 )BWM@&3!M2ԉOF$ (=߇GS^lq3!$F &[Wܷ۶YDTU Be15@fJțF15e WQC2ZI4HRR*&U-u_ZF{7M1#Ri5_Vf,jUfʉRثmZ)e#&&m&26&6EAiIje-fYda2jݶa Jf6%4BJZ"Ʀ a*EY1JmiDj+&MR,FdM44MHP DdMDK(EFH##bRQ("bK"P$(IFi#&1``e&1fyb-dejɨ6XMb^CfF_7:,-*%vi6%6EbcX$IR#e61c ީ~[a2- JY#RzMIh&-]j팘ԦH)%%mX`iV]Ͷ6SdQF"*PJ7̙6F$fقM5MɆ\]&aDb&K_L!,QmU$[Z-l[c[EmjMI R64,ze5!dfRCHQդMEZJ-EFfY(1dIQhԱVe"5Tj*̠KKRK|owZi6Z5U+cH[jmU-ƪ6 ͵%e2bS@mUr$(>>WWv_࿗~oL.i)sbty=b+}|O |^.!_W@|zxjOTHn,GiOiJߑcȆݩ ya)!hxxCE]rgm:]95y"cԑlG"ݪbBФMyuսpXS!a~yHA6RsVi|LTD^pu/t&ҏڏ}R6DsMܓ#])gD]]z& ]q#ʆB7z&ʗB x!~^8:3!He$|x4iG;oҩ`5jEQO#gO;F6^p6~HiHOe(nT'#%GcYAyg .! c`q0'/$-DǞxihtcvr_|ޏ,8z}ImxKQ}> @ϓk"lx8\ԝVD P3Ë+CxmH)Ec k0xg>$IwݩwgvHx" "O< Xh|i_ 7yꎀBJ¯Ik'HΨ- vQDj QT3 ȶ{m6XPOi)t'nϦɦξc7ԓ{QSJ wSyyYmᵬTagKGW_t14bt$gZ[a`nmLM]tC%=>^]Y=L=+ڸ`Hq~--M2AD&!;\/C({6Nb/$ĄCdԔɠ1jFn({=3e1?ɺ_mN;!%K,SO83n{r+7z{oi)4 sȦI:YqH-1KdQlYQDL?fe=77оoоSj/" ,,vd(#2-(,6_H $D ! ȹn9ay~ b^)OHe%Gj e L )o/;_SM= |О>Yr8vU!J/D]<8!1"(e]P @"vjPL} ?POgV{ĴCmYn0:CMy Owr_\q}YS1/iQkZ OɆݎƘ {wϔ܂T߃NtP@1/ LMG(hݶ%nQk5}m|'#ׯDŽ/5BK%~Lpvc -CCX̢\Kw&vZ?}c&ǁf|4r{5kqK^n2VR6XciNC++rE^vTvn|Y:7L/s3lq5LL&bmKU%JxE76{okIwBR$"&fksPW,%s&Wo=/}NN-~[%YLW+}xyXZIxq& /FLPݏ\\[A;C