github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/libkb/stream_classifier_test.go (about) 1 // Copyright 2015 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 4 package libkb 5 6 import ( 7 "bytes" 8 "encoding/base64" 9 "io" 10 11 "testing" 12 13 "github.com/stretchr/testify/require" 14 ) 15 16 func newStreamFromBase64String(t *testing.T, s string) io.Reader { 17 buf, err := base64.StdEncoding.DecodeString(s) 18 if err != nil { 19 t.Fatal(err) 20 } 21 return bytes.NewReader(buf) 22 } 23 24 func assertStreamEqBase64(t *testing.T, r io.Reader, m string) { 25 buf, err := io.ReadAll(r) 26 if err != nil { 27 t.Fatalf("an error occurred during stream draining") 28 } 29 m2 := base64.StdEncoding.EncodeToString(buf) 30 if m != m2 { 31 t.Fatalf("the whole stream came back out") 32 } 33 } 34 35 type testVector struct { 36 msg string 37 sc StreamClassification 38 } 39 40 func TestClassifyTestVectors(t *testing.T) { 41 42 vectors := []testVector{ 43 { 44 msg: `owEBPQHC/pANAwAKAZgKPw0B/gTfAcsNYgBWiR6fZm9vYmFyCokBHAQAAQoABgUCVokenwAKCRCYCj8NAf4E38UACACoF9R9FJnZX7VqhHpOFgWgQR9wn8XJQ6DI7kkrlO1sF9OH3KoShuPT1G3J8/c4HXWY4qLluDfDN0sFA1Obt6PLQ4PJxWgZzuTed+f/zJ9NiQc2XdqT/iUPSEvWFKHI+1apF04iCjBs4dJaJOPAZdq4ZZ/7LAi8GwwDY5v3FJvwur180568tTcVTQtZqg3IhFGCMVZwD/S4x6DNdRxQB796SgbyGg/B8A9/vUEjMuUv6XU2sJcNNXuRfWYX0E+gsRg0kwjQlDOHvB+mDtu/qxVAd/Zm2y7NCoEHBH2jLI50Ls2OTHf98p43oHMofoQCnzP0nRu7bu4W4lVFEIqIXZvO`, 45 sc: StreamClassification{ 46 Format: CryptoMessageFormatPGP, 47 Type: CryptoMessageTypeAttachedSignature, 48 Armored: false, 49 }, 50 }, { 51 msg: "hQEMA5gKPw0B/gTfAQf/W3Ra0uwZvzn3pxIcLTOFodqI5tsb3aZdIlfo/O36ekkbubizGrtSbc2rA23HeZOgWHM5zwsf6GU9UwG1ToC/ORtemQuAwx08DSr3NbSSxyyiPI+6936TVCxnXMBEBSvk20rhDeLFiqnuDzrtWcnHAKYIQ8XG6HfRN2ibvn8nvLH+dfuQhzNx9bsHSCKRyV44ziExScoSW8TJdenpXg1UoYKG4Ti/t5QGaiGZEZIkjM+bVR4jHzUmY0VFso8OfN4rn2rbQtvbV50oRDgxKOsfJTxvs0nsXiOsviaFA62fUiXXv4bWsDTB5urpovzjuzUw/VlWyBZTuIuAshcrBo4RnNJVAb0yxFCLt+BbwUTQoOWzTC5hWBgivG/lYTpbGJ/C4xWQCszy/IXb7ZPDiH+i/V4DRh2LrF/AOql8sh0Qx9j3mJUHaYaWv6K1wptOvLEF02iZWyhWGg==", 52 sc: StreamClassification{ 53 Format: CryptoMessageFormatPGP, 54 Type: CryptoMessageTypeEncryption, 55 Armored: false, 56 }, 57 }, { 58 msg: "iQEcBAABCgAGBQJWiYjOAAoJEJgKPw0B/gTfASkH+wSCsUYLOMbeWUSil0C96T3Ug5vhZ/kd/UThhs+06FSxvvD9t9oTLQnJmYjV3zHmgQ/w0kc5ue00r8WMJelatE9y/TwTfiRgyRbs/5Y95GBiy/KBu2ygZ5tDt/jEaH5bHh3v86cSf9e70oxvqvSof6KFIWIQBZM87Y4TCrVHIQ2VrXm7DASPaSKo8fv+6bEHn18ii9U4IpOPUD7mxM9jr5388mFGBSe/2+L5o1mHwpfpLXUxt0Hehv9mAhzwy4WNszWg25BIbwZ65THrfbw938KDIkymE0bFfMXbY252HEEstUmKAFZ5obalryu851QPjTlW/eQnBS/ahvYS1q/3g8k=", 59 sc: StreamClassification{ 60 Format: CryptoMessageFormatPGP, 61 Type: CryptoMessageTypeDetachedSignature, 62 Armored: false, 63 }, 64 }, { 65 msg: "LS0tLS1CRUdJTiBQR1AgU0lHTkFUVVJFLS0tLS0KQ29tbWVudDogR1BHVG9vbHMgLSBodHRwczovL2dwZ3Rvb2xzLm9yZwoKaVFFY0JBQUJDZ0FHQlFKV2lZb3FBQW9KRUpnS1B3MEIvZ1RmMUxRSC9SQk1xbzh3bXQyRUx6T0xuaEVWOVB3VgpRa00yTHh4WktOU216MmtxWDBNQytrWW11STU5ZExSS1EvaEx3V0JtcllzSjZqMUxkVnB0Z0JwdmEwbUhFRmNUCmdyTnZiMk14ZDdkdEpFQkJvRVdob3JzMTZUY0lDQ2lRazczRUc5TDZ4TUZrSU5aNEVkeFRxRDNzRllHSjduRkQKQktiNmV6RHBDVit4dnFRdTRMRGxsd2Q0WDFaOVo1RFR1R2VNNld4MVQ2cFRLNTVNeXZHZ0ZnQ011ZmJxd3hQKwpBVWFlbFVlRlYzbUtXN1R4Q0s3cVo0Um9GaC9zR1VOKytpcWo2NGF1MjRLeEpGdHVCbVk1LzFNbEt4ckJHVEVsCkJPV3dFdnhnK3MvWFFGcllmeFVDLzNQWVNINDFObklwVGVGZE9nTlZNRDAzWElrMEU5TmtJZ0c5SG54WVI3TT0KPXo4c1MKLS0tLS1FTkQgUEdQIFNJR05BVFVSRS0tLS0tCg==", 66 sc: StreamClassification{ 67 Format: CryptoMessageFormatPGP, 68 Type: CryptoMessageTypeDetachedSignature, 69 Armored: true, 70 }, 71 }, { 72 // This one is an attached signature 73 msg: "LS0tLS1CRUdJTiBQR1AgTUVTU0FHRS0tLS0tCkNvbW1lbnQ6IEdQR1Rvb2xzIC0gaHR0cHM6Ly9ncGd0b29scy5vcmcKCm93RUJWQUdyL3BBTkF3QUtBWmdLUHcwQi9nVGZBY3NrWWdCV2lZdG1UbTkwYUdsdVp5QjNhV3hzSUdOdmJXVWcKYjJZZ2JtOTBhR2x1Wnk0S2lRRWNCQUFCQ2dBR0JRSldpWXRtQUFvSkVKZ0tQdzBCL2dUZmpvWUlBTHBiOStLVwo4OERJK2svRFBVc2JzSkN2d0RlRlZhN1BKZXF3VFNQQ2Y5cjhzVUFnZWVWcXVXM0JHNjkyNkgrV3lucG56cUF1ClBiY21SZ29XdWNVRVZPSHBYZkxsN292UkwxSURLYkJVcXNQUE5yUGdudUxzblY4NVJKMkkrOUxMYTM2SUptaE0KNFppM25sWU0xeGdYKzhQNm92TWdUeTQybzRSMTgrMStlZ1RDQ0grbVlhMkVKd1hEdGJ4T3AyQXN6aENrNlNlbwo2NjdxRllNOTdzYXk4ZlZUVkFwZlYrY0RJdHRxc01mcUJSMHJwZ1Vlb1ROdk5kNDlDVmVsSmVGMzdhOWt4UWpuCklPcmUrWmJjRzNKNUtOek1YZHpTT0xYcjNGWm42K2VCclBXSmZVemtrbVlmQnhucnhRcFpPVjA0Z09vZ05IK2YKLzBLRHZ4SktVYytrandRPQo9Sk1iNgotLS0tLUVORCBQR1AgTUVTU0FHRS0tLS0tCg==", 74 sc: StreamClassification{ 75 Format: CryptoMessageFormatPGP, 76 Type: CryptoMessageTypeAmbiguous, 77 Armored: true, 78 }, 79 }, { 80 // This one is an encryption 81 msg: "LS0tLS1CRUdJTiBQR1AgTUVTU0FHRS0tLS0tCkNvbW1lbnQ6IEdQR1Rvb2xzIC0gaHR0cHM6Ly9ncGd0b29scy5vcmcKCmhRRU1BeW5BcEhsdHBqT3JBUWY4Q0s1YTBSUmNLTFYrTEk2RDZjeEdYRDNhZmlZZFRVNy9KbVBzaWo4ZmF6VHgKcTk4SDRCYXY1WjJiZTRpY3UvMWh0S05iRjZyUG9GL0NWT0EwOXM4M09QYlJwd2doc2RScEVlMDhHQk5WVHFXOQpUQ253RmhKZHNUT21NUlMzTGZTZEFuT1RDcDVONXJLME41Rzl3cUdkZmtFT3NLN0dVdWpDYlh2M3pXWTZVeEF4Cm10Zi9jMU1SVGFPdDlUT1FidkhDK29xTkRENklNQ093bUo0OTVsVDJrUzBIaUd5Z1RPT003RjhNVEkvSmpLMSsKRWZ5SnRqdHlPK2FZS2VGQ053N3pseUZQWnQyWmRtb0VCVW1tZmcrYW1Icko2WHpTSjFIU0Vvd1lESFptSm9Wdgo5RlNteVd5ZUw1dkNmeHYyaTJZYkRKUk1LYjl1b2RxMGRIODNWdmV1SE5KUkFSa1FxTlRlb1BJN0VkVDQvS05LCjJCYmZBVWwydXZmSHh6MTBRbFRxYXorVmFRZ3poTDdnWFc5OFZvOXQwWldjWGg3bUEyQWozd2d3aElHdUt4MVgKQ2tzcE9IczVDb3pTOXdHdEFINnA1b1FhCj1lNXVxCi0tLS0tRU5EIFBHUCBNRVNTQUdFLS0tLS0K", 82 sc: StreamClassification{ 83 Format: CryptoMessageFormatPGP, 84 Type: CryptoMessageTypeAmbiguous, 85 Armored: true, 86 }, 87 }, { 88 // This is made by removing the armor and base62 decoding before base64 encoding 89 msg: "xFKVqHNhbHRwYWNrkgEAAcQgh5CBmJBG4rn55pNyntYpIGC7tTnXqKAwNEsKRUg2rcDEIBzNGdKOORv7lrE9ne4DnkLP16QTJ/O2Z5ph8OY+6ySBksRAut3Y6fqyNi0uRf4L5+xCEULkVWIextzFccdu3iuxoiKz47Y4IYjfasZMggbMY+QyZTPfTww3RfjASM64fR60DcQDZm9vksRA9MRowgZFqvlev2E2RbL8rBh5MTeKpNwi6oT6d95XBzzUyBrDiB3frwBQ5uNzpLdXQGqQYDzB4Dx8ZPoldtv+AMQA", 90 sc: StreamClassification{ 91 Format: CryptoMessageFormatSaltpack, 92 Type: CryptoMessageTypeAttachedSignature, 93 Armored: false, 94 }, 95 }, { 96 // This is made by base64 encoding the cyphertext, including armor, with no binary step between 97 msg: "QkVHSU4gS0VZQkFTRSBTQUxUUEFDSyBTSUdORUQgTUVTU0FHRS4ga1lNNWgxcGc2cXo5VU1uIGo2RzdLQjJPVWZ1MFdJaSAxWmZ5amRjWVZ3dUwwOWsgZTMzZWpnbWFObWZWckdQIDNLMlZSbTFaSUtNY1pRMCBPQjFyd1VqRjNPZnVSSkQgOVBMSmtDcFU4RnFvZFlQIHV4UlFwdjZ3aG1LUVRnTiBqbkEyYkFrNzRHYjJDTzYgdmNXbkFoTTdSUGlBYzFYIGFrMGx6RDVxMlNOT2diNyBreUphOEwwSThwSndHR1ggemdFS1QyNXlWcEZqanhiIGZ5MUc4anFaYTdpUDZqTSBrb3RMb2taZDJoYzBsdWQgQWROb2w0bGRIQ2VSR20wIFZpOXpFOTA5Vk5RS3Z1QSA0dWFsUnhTRmlyUWhqUzMgQXdEU21kU09mTHJuOThEIFpVTmNsVTMwMnlzeUJsNSBnMDAuIEVORCBLRVlCQVNFIFNBTFRQQUNLIFNJR05FRCBNRVNTQUdFLgo=", 98 sc: StreamClassification{ 99 Format: CryptoMessageFormatSaltpack, 100 Type: CryptoMessageTypeAttachedSignature, 101 Armored: true, 102 }, 103 }, { 104 msg: "LS0tLS1CRUdJTiBQR1AgU0lHTkVEIE1FU1NBR0UtLS0tLQpIYXNoOiBTSEE1MTIKCmZvbwotLS0tLUJFR0lOIFBHUCBTSUdOQVRVUkUtLS0tLQpDb21tZW50OiBHUEdUb29scyAtIGh0dHBzOi8vZ3BndG9vbHMub3JnCgppUUVjQkFFQkNnQUdCUUpXaXZHcEFBb0pFSmdLUHcwQi9nVGZNN0VJQUxsSFovNGV2STVqelZvKzRPbEJ3VDdICk5sL2xMRWJCK1phU0VtOEhYcmRPa3dleEErMjYyOHJUeW1ORXMzUXFhNVR5cVZ3VXdGdHc3YmYyUVJSenJFRkQKZ3lUbW94dDAwajkyNjBFNkEzU1dRc1Z4MW5IVngxVGpTSkdYdlFNUFp4eENvQnhidkJWY2dtUjN2Y3ppeDZNUgpYemNnMjVhOGZJbjEraGM4S1RmZ1BhaTRjZjZVb1VrMnp0dUdDVFVYRDJqL3BBb0xHTnVRY0RSL0x2UlFwY2pmCjdVYkQ1YVNsMGRZVDdqTmRUV0RGSk01cFhVcVZYejhlTHA4MlRTdU1DUW5jYVhDT0VseXV6eVFwY0NhRUQ0WkMKNFc0dlk5SXpqYWhJRHVrQXpaT3FtNTdzMiszd3gzdjZkUVVTRkVNM01YY1pGSW5IWTNaWDRDMVM3ZU9MbE5VPQo9VEY3eAotLS0tLUVORCBQR1AgU0lHTkFUVVJFLS0tLS0K", 105 sc: StreamClassification{ 106 Format: CryptoMessageFormatPGP, 107 Type: CryptoMessageTypeClearSignature, 108 Armored: true, 109 }, 110 }, 111 } 112 113 for i, v := range vectors { 114 t.Logf("--> Vector %d\n", i) 115 r := newStreamFromBase64String(t, v.msg) 116 sc, r2, err := ClassifyStream(r) 117 if err != nil { 118 t.Fatalf("an error occurred while stream classifying (%d)", i) 119 } 120 if sc.Format != v.sc.Format { 121 t.Fatalf("Bad format (%d)", i) 122 } 123 if sc.Type != v.sc.Type { 124 t.Fatalf("bad type (%d)", i) 125 } 126 if sc.Armored != v.sc.Armored { 127 t.Fatalf("bad armored value (%d)", i) 128 } 129 assertStreamEqBase64(t, r2, v.msg) 130 } 131 } 132 133 func TestClassifyBadVectors(t *testing.T) { 134 _, _, err := ClassifyStream(bytes.NewBufferString("\n\n\n\n\n\n\n\n")) 135 require.Error(t, err) 136 require.IsType(t, UnknownStreamError{}, err) 137 }