前言 前言是很重要的,前言可以知道,为什么要做这件事,为什么会有这篇博客。2月底到3月初的时候,进行某一个项目时,由于需要大量数据的运算与处理,Python速度过慢,而C写起来又很慢,为了效率(实在没效率),临时使用了静态编译的go语言来实现相应的功能需求,并在当时学习了一些go的基本使用手法。时间过了很久,很多当时学会的技巧也都忘的差不多了,本篇,本想着和shell篇一样,从源码的角度进行分析(本篇敏感字段仅有真实的Salt值,随便设置一个即可),以后对类似功能有需求时,可以有一些参考的价值。但又不完全一样,go不是shell,不是简单知道怎么用就行的。因此,本篇仅作为一个引导,并不会做到一个完全细致的分析。我会根据当时的需求,列出两份我之前写的能跑起来的代码(已脱敏),并罗列代码中用到的技术以及我当时查阅的一些资料。因为短期用不上Go,它也不是我主流使用的语言,并且大部分情况下,需要什么功能查询一下就好了,所以等到某一天,我又因为某些任务,开始编写go代码的时候,再将本篇的内容进行补充与扩展。建议以后进一步扩展文章内容时,先读完文末链接的2本书,并参考开源源码后,再进行适当补充。
需求分析 需求a
给定特定的盐值
生成所有IPv4地址 (42亿)与加盐哈希(使用sha256)后的对应关系
根据哈希值前2位,将对应关系存在相应的csv文件中
例如哈希值前2位为FF,则将对应关系存在255.csv中
从0.csv~255.csv,共建立256个相应的csv文件
需求b
给定特定的盐值
从给定的csv文件/json文件中读取域名
生成所有域名 与加盐哈希(使用sha256)后的对应关系
进行需求a的3~5步
应用技术 字符串操作
CSDN:golang strconv Atoi Itoa 例子
CSDN:golang 中 strings 包的 Replace 用法介绍
CSDN:Go strings.Split函数
Go语言中文网:strings包里面的Split函数的坑
简书:Go语言的string和byte slice之间的转换
Slice 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 type slice struct { array unsafe.Pointer len int cap int } 1. 切片(slice)和数组类似,也是表示一个有序元素,但这个序列的长度可变2. 切片是对底层数组一个连续片段的引用,所以是引用类型3. 切片内部实现的数据结构通过指针引用底层数组,设定相关属性将数据读写操作限定在指定的区域内4. 切片本身是一个只读对象,其工作机制类似数组指针的一种封装5. 多个切片可以指向同一个底层数组,实现了内存共享mySlice := make ([]type , len , cap ) mySlice1 := make ([]int , 5 ) mySlice2 := make ([]int , 5 , 10 ) mySlice3 := []int {10 , 20 , 30 , 40 , 50 }
Map
简书:Go内建函数make及切片slice、映射map详解
sync.map
博客园:深度解密Go语言之sync.map
反射
Go语言设计与实现:反射
The Go Programming Language:通过reflect.Value修改值
vimsky.com:reflect.New()用法及代码示例
Json解析
StackOverFLow:Go Unmarshal reflect.Type got map[string] interface{}
博客园:Go的Json解析-Marshal与Unmarshal
哈希计算
CSDN:Go sha256使用实例介绍
跨平台编译
知乎:Go交叉编译(跨平台编译)
StackOverFlow:Go 1.7 Cross Compilation from Windows to Linux/Ubuntu
代码实现 需求a 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 package mainimport ( "crypto/hmac" "crypto/sha256" "encoding/csv" "encoding/hex" "fmt" "os" "reflect" "strconv" "strings" "sync" ) func fatal (e error) { if e != nil { panic (e) } } func calculate_hash (ip string ) (ip_hash string ) { key := "AAAABBBBCCCCDDDDEEEE11112222333344445555++++----" keyb := []byte (key) ipb := []byte (ip) mac := hmac.New(sha256.New, keyb) mac.Write(ipb) msgmac := mac.Sum(nil ) hash_code := strings.ToUpper(hex.EncodeToString(msgmac)) return hash_code } func initial_syncmap (fp_map sync.Map) (ret_map sync.Map) { for i := 0 ; i <= 255 ; i++ { key := strconv.Itoa(i) filename := "iptab_hmac256\\" + key + ".csv" f, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE, 0666 ) fatal(err) fp_map.Store(key, f) } return fp_map } func free_syncmap (fp_map sync.Map) { for i := 0 ; i <= 255 ; i++ { key := strconv.Itoa(i) f, ok := fp_map.Load(key) if ok == false { fmt.Println("Nothing Find!" ) } f_elem := reflect.ValueOf(f).Elem() f_addr := f_elem.Addr().Interface().(*os.File) var fp *os.File fp = f_addr fp.Close() } fmt.Println("Over!" ) } func generate_and_writein (start_ip string , c chan int , fp_map sync.Map) { ip_addr := []string {"1" , "0" , "0" , "0" } ip_addr[0 ] = start_ip elements := make ([]string , 2 ) for { num_3, _ := strconv.Atoi(ip_addr[3 ]) num_2, _ := strconv.Atoi(ip_addr[2 ]) num_1, _ := strconv.Atoi(ip_addr[1 ]) if num_3 < 255 { num_3++ ip_addr[3 ] = strconv.Itoa(num_3) ip_str := strings.Join(ip_addr, "." ) ip_hash := calculate_hash(ip_str) str_hex_uid := ip_hash[0 :2 ] uid, err := hex.DecodeString(str_hex_uid) fatal(err) fmt.Println(uid[0 ], " " , ip_str, " " , ip_hash) str_uid := strconv.Itoa(int (uid[0 ])) filename := str_uid f, _ := fp_map.Load(filename) f_elem := reflect.ValueOf(f).Elem() f_addr := f_elem.Addr().Interface().(*os.File) var fp *os.File fp = f_addr elements[0 ] = ip_str elements[1 ] = ip_hash w := csv.NewWriter(fp) w.Write(elements) w.Flush() continue } else if num_2 < 255 { ip_addr[3 ] = strconv.Itoa(0 ) num_2++ ip_addr[2 ] = strconv.Itoa(num_2) continue } else if num_1 < 255 { ip_addr[2 ] = strconv.Itoa(0 ) num_1++ ip_addr[1 ] = strconv.Itoa(num_1) continue } else if num_1 == 255 && num_2 == 255 && num_3 == 255 { break } } } func main () { var fp_map sync.Map fp_map = initial_syncmap(fp_map) c := make (chan int ) for i := 1 ; i <= 255 ; i++ { if i == 10 || i == 127 || i == 256 { continue } start_ip := strconv.Itoa(i) go generate_and_writein(start_ip, c, fp_map) } wait := <-c fmt.Println(wait) free_syncmap(fp_map) }
需求b 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 func readCsv (fp_map sync.Map) { filename := "domain.csv" f, err := os.Open(filename) fatal(err) defer f.Close() r := csv.NewReader(f) for { row, err := r.Read() fatal(err) domain := row[0 ] calculateHash(fp_map, domain) } } func readCsv (fp_map sync.Map) { for i := 1574 ; i <= 3145 ; i++ { prefix := strconv.Itoa(i) filename := "origin_csv\\" + prefix + "_full.csv" f, err := os.Open(filename) if err == nil { fmt.Println(filename) r := csv.NewReader(f) for { row, err := r.Read() if err != nil { break } domain := row[0 ] calculateHash(fp_map, domain) } f.Close() } } } type ( ixx_detail struct { Hxxx string `json":hxxx"` Poxx string `json":poxx"` Paxx string `json":paxx"` } intellxxxxxx_info struct { Type string `json":type"` Alxxx bool `json":alxxx"` Status string `json":status"` Rixx string `json":rixx"` Confixxxxx string `json":confixxxxx"` Maxxxxxxx_type uint8 `json":maxxxxxxx_type"` Maxxxxxxx_fxxxxx string `json":maxxxxxxx_fxxxxx"` Camxxxxx string `json":camxxxxx"` Cxxtxxl_type string `json":cxxtxxl_type"` Hox bool `json":hox"` Protoxxx string `json":protoxxx"` First_sxxx uint64 `json":first_sxxx"` Last_sxxx uint64 `json":last_sxxx"` Ixx string `json":ixx"` Ixx_detail ixx_detail `json":ixx_detail"` Tags []string `json":tags"` } ) func read_and_write (fp_map sync.Map) { file, err := os.Open("domain.json" ) fatal(err) defer file.Close() scanner := bufio.NewScanner(file) for scanner.Scan() { json_str := scanner.Text() json_bytes := []byte (json_str) data := intellxxxxxx_info{} err = json.Unmarshal(json_bytes, &data) fatal(err) str_hex_uid := data.Ioc[0 :2 ] uid, err := hex.DecodeString(str_hex_uid) fatal(err) str_uid := strconv.Itoa(int (uid[0 ])) filename := str_uid f, _ := fp_map.Load(filename) f_elem := reflect.ValueOf(f).Elem() f_addr := f_elem.Addr().Interface().(*os.File) var fp *os.File fp = f_addr fp.Close() elements := make ([]string , 16 ) elements[0 ] = data.Type if data.Alert { elements[1 ] = "true" } else { elements[1 ] = "" } continue } }
参考链接
Go语言设计与实现
Go语言圣经(中文版)
Go源码库