当前位置: 首页 > news >正文

信息发布型企业网站的特点外贸网站商城

信息发布型企业网站的特点,外贸网站商城,wordpress地图无插件,在域名做网站代码非常长 有六百多行 参考一位博主的理论实现 通俗易懂#xff0c;十分钟读懂DES 还有很多不足的地方 感觉只是个思路 S盒#xff08;理论既定#xff09; package src// 定义S - 盒的置换表 var SBoxes [8][4][16]int{{{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, …代码非常长 有六百多行 参考一位博主的理论实现 通俗易懂十分钟读懂DES 还有很多不足的地方 感觉只是个思路 S盒理论既定 package src// 定义S - 盒的置换表 var SBoxes [8][4][16]int{{{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},{0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},{4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},{15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13},},{{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},{3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},{0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},{13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9},},{{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},{13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},{13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},{1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12},},{{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},{13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},{10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},{3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14},},{{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},{14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},{4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},{11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3},},{{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},{10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},{9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},{4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13},},{{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},{13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},{1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},{6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12},},{{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},{1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},{7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},{2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11},}, }主代码 可以适应各种输入 但是时间有限没能调通 位运算真的折磨人悲 package mainimport (bufiocrypto/randencoding/binaryfmtmain/srcosstrings )// 如果不足六十四位密钥 进行随机填充 func PadKeyWithRandom(key []byte) []byte {// 输出原始密钥长度fmt.Println(原始密钥长度, len(key))// 计算需要填充的字节数padLen : 8 - len(key)// 创建一个新的字节切片长度为64位 8字节newKey : make([]byte, 8)// 复制原始密钥到新密钥的开头copy(newKey, key)// 生成随机字节填充剩余字节randomBytes : make([]byte, padLen)_, err : rand.Read(randomBytes)if err ! nil {panic(err)}// 将随机字节添加到密钥for i : len(key); i 8; i {newKey[i] randomBytes[i-len(key)]}// 输出填充后的密钥长度fmt.Println(填充后的密钥长度, len(newKey))return newKey }// 如果明文不足64位bit 就填充 func PadPlaintext(plaintext []byte) []byte {for len(plaintext) 8 {plaintext append(plaintext, 0x00)}return plaintext }// 初始置换 最开始 func InitialPermutation(text []byte) []byte {if len(text) ! 8 {panic(Invalid len of 64 bits for Init)}var piece [][]int{{58, 50, 42, 34, 26, 18, 10, 2},{60, 52, 44, 36, 28, 20, 12, 4},{62, 54, 46, 38, 30, 22, 14, 6},{64, 56, 48, 40, 32, 24, 16, 8},{57, 49, 41, 33, 25, 17, 9, 1},{59, 51, 43, 35, 27, 19, 11, 3},{61, 53, 45, 37, 29, 21, 13, 5},{63, 55, 47, 39, 31, 23, 15, 7},}result : make([]byte, 8)for i : 0; i len(piece); i {for j : 0; j 8; j {index : piece[i][j] - 1// 确定该比特位所在的字节在整个密钥字节切片中的某个字节索引byteIndex : index / 8// 在当前字节内要处理的比特位相对于字节最高位第 7 位的偏移量 就是先确定某个字节再瞬移到要取的比特位bitOffset : 7 - (index % 8)// 分前后四字节的两段// key[bitIndex/8]就是简单的选定要找的字节// (1 (7 - (bitIndex % 8)))作用是挪动1去某个位置通过与操作来提取出原始字节中我们想要的那个比特位// 然后开始为放入c0服务// 将前面提取出的比特位再向右移动 7 - (bitIndex % 8) 位这一步的目的是将提取出的比特位调整到最低位// 最后将调整到最低位的比特位再向左移动 bitOffset 位这样就可以将该比特位设置到 c0 中相应字节的正确位置上result[byteIndex] | (text[index/8] (1 (7 - (index % 8)))) (7 - (index % 8)) bitOffset}}fmt.Printf(明文/密文 初始置换结果%v\n, result)return result }// 逆置换 最后 func ReversePermutation(text []byte) []byte {if len(text) ! 8 {panic(Invalid len of 64 bits for Reverse)}var piece [][]int{{40, 8, 48, 16, 56, 24, 64, 32},{39, 7, 47, 15, 55, 23, 63, 31},{38, 6, 46, 14, 54, 22, 62, 30},{37, 5, 45, 13, 53, 21, 61, 29},{36, 4, 44, 12, 52, 20, 60, 28},{35, 3, 43, 11, 51, 19, 59, 27},{34, 2, 42, 10, 50, 18, 58, 26},{33, 1, 41, 9, 49, 17, 57, 25},}result : make([]byte, 8)for i : 0; i len(piece); i {for j : 0; j 8; j {index : piece[i][j] - 1// 确定该比特位所在的字节在整个密钥字节切片中的某个字节索引byteIndex : index / 8// 在当前字节内要处理的比特位相对于字节最高位第 7 位的偏移量 就是先确定某个字节再瞬移到要取的比特位bitOffset : 7 - (index % 8)result[byteIndex] | (text[index/8] (1 (7 - (index % 8)))) (7 - (index % 8)) bitOffset}}return result }// 拆开得L0和R0 func SplitLR(text []byte) ([]byte, []byte) {if len(text) ! 8 {panic(Invalid SplitLR of 64 bits)}left : text[0:4]right : text[4:8]return left, right }// 拼起来L16和R16 func MergeLR(left, right []byte) []byte {if len(left) ! 4 || len(right) ! 4 {panic(Invalid left or right for MergeLR 64 bits size)}text : make([]byte, 8)copy(text[0:4], left)copy(text[4:8], right)return text }/* // 每个加密轮应该包括扩展、生成每轮子密钥、进行异或、S盒、P盒 func Encrypt(L, R []byte) ([]byte, []byte) {Expand32To48(R) } */// 1. 扩展32-48 func Expand32To48(input []byte) []byte {if len(input) ! 4 {panic(Invalid len of 32bits(4 bytes) for Expand32To48)}// 置换表permutationTable : [][]int{{32, 1, 2, 3, 4, 5},{4, 5, 6, 7, 8, 9},{8, 9, 10, 11, 12, 13},{12, 13, 14, 15, 16, 17},{16, 17, 18, 19, 20, 21},{20, 21, 22, 23, 24, 25},{24, 25, 26, 27, 28, 29},{28, 29, 30, 31, 32, 1},}result : make([]byte, 6)var bitcount 0 //用于统计result的比特位置var bittarget 0 //统计result放入的具体偏移量for row : 0; row len(permutationTable); row {for col : 0; col len(permutationTable[row]); col {index : permutationTable[row][col] - 1bittarget bitcount % 8result[bitcount/8] input[index/8] (1 (7 - (index % 8))) (7 - (index % 8)) bittargetbitcount}}return result }// 2. 生成子密钥 // 密钥调度算法可以将64位的主密钥分成16个子密钥每个子密钥48位用于每轮加密中与输入数据进行异或运算。 func GenerateSubkey(key []byte) [][]byte {// 置换选择1C0, D0 : PC1Permutation(key)var subkeys [][]bytefor i : 1; i 16; i {c : CircularLeftShift(C0, i)d : CircularLeftShift(D0, i)subkey : PC2Permutation(c, d)subkeys append(subkeys, subkey)// 详细打印当前生成的子密钥内容fmt.Printf(生成第 %d 个 子密钥\n, i)fmt.Printf(子密钥内容十六进制)for _, b : range subkey {fmt.Printf(%02x , b)}fmt.Println()// 更新左移结果 一共十六轮C0 cD0 d}fmt.Println()return subkeys}// 2.1 实现PC - 1置换操作 func PC1Permutation(key []byte) ([]byte, []byte) {if len(key) ! 8 {panic(Invalid key length for PC1Permutation. Expected 8 bytes (64 bits).)}pc1Table : [][]int{{57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18},{10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36},{63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22},{14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4},}c0 : make([]byte, 4)d0 : make([]byte, 4)for i : 0; i len(pc1Table); i {for j : 0; j len(pc1Table[i]); j {// 要处理原始密钥中的第 pc表值-1 个比特位bitIndex : pc1Table[i][j] - 1// 确定该比特位所在的字节在整个密钥字节切片中的某个字节索引byteIndex : bitIndex / 8// 在当前字节内要处理的比特位相对于字节最高位第 7 位的偏移量 就是先确定某个字节再瞬移到要取的比特位bitOffset : 7 - (bitIndex % 8)// 分前后四字节的两段if byteIndex 4 {// key[bitIndex/8]就是简单的选定要找的字节// (1 (7 - (bitIndex % 8)))作用是挪动1去某个位置通过与操作来提取出原始字节中我们想要的那个比特位// 然后开始为放入c0服务// 将前面提取出的比特位再向右移动 7 - (bitIndex % 8) 位这一步的目的是将提取出的比特位调整到最低位// 最后将调整到最低位的比特位再向左移动 bitOffset 位这样就可以将该比特位设置到 c0 中相应字节的正确位置上c0[byteIndex] | (key[bitIndex/8] (1 (7 - (bitIndex % 8)))) (7 - (bitIndex % 8)) bitOffset// 输出提取后比特位在c0中的位置//fmt.Printf(提取后比特位在c0中的位置: %d\n, byteIndex)// 输出c0的当前状态//fmt.Printf(c0当前状态: %v\n, c0)} else {// 减去 4因为 d0 是从原始密钥经过处理后得到的后半部分 其他类同d0[byteIndex-4] | (key[bitIndex/8] (1 (7 - (bitIndex % 8)))) (7 - (bitIndex % 8)) bitOffset}}}fmt.Println(PC-1置换结果如下)fmt.Println(c0 length:, len(c0))fmt.Println(c0 content:, c0)fmt.Println(d0 length:, len(d0))fmt.Println(d0 content:, d0)return c0, d0}// 2.2 循环左移操作 func CircularLeftShift(data []byte, times int) []byte {num : binary.BigEndian.Uint32(data)// 将uint32转换为二进制字符串binaryStr : fmt.Sprintf(%032b, num)fmt.Printf(num的二进制表示: %s\n, binaryStr)result : make([]byte, 4)if times 16 || times 1 {panic(ShiftLeft Error)}var shiftTable [16]int{1, 1, 2, 2, 2, 2, 2, 2,1, 2, 2, 2, 2, 2, 2, 1,}// 由于在数值中高位在左低位在右所以采用右移在大端模式下是左移var out uint32 numfor i : 0; i shiftTable[times-1]; i {// 获取最低位h : num 1//fmt.Printf(h:%d\n, h)outStr : fmt.Sprintf(%032b, out)fmt.Printf(out之前的二进制表示: %s\n, outStr)// 先将out整体左移一位out 1// 当h为0时进行特殊处理将num的最高位补到out的最低位if h 0 {// 获取num的最高位highestBit : num 31// 将num的最高位补到out的最低位out | highestBit} else {// 当h不为0时直接将h补到out的最低位out | h}outStr fmt.Sprintf(%032b, out)fmt.Printf(out左移1次后的二进制表示: %s\n, outStr)// 同时对num也进行类似的左移操作保持数据状态的一致性num 1// 如果num超过了uint32的范围进行处理比如截断等这里简单示例截断if num (132 - 1) {num (132 - 1)}}binary.BigEndian.PutUint32(result, out)// 将uint32转换为二进制字符串resStr : fmt.Sprintf(%08b, result)fmt.Printf(result的二进制表示: %s\n, resStr)return result }// 2.3 PC-2置换 func PC2Permutation(c []byte, d []byte) []byte {// totalBits : 56// 这里totalBits应该是56因为c0和d0都是4字节32位拼接起来就是56位// fmt.Printf(totalbits:%d\n, totalBits)// 不含奇偶校验位第 8、16、24、32、40、48、56位pc2Table : [][]int{{14, 17, 11, 24, 1, 5},{3, 28, 15, 6, 21, 10},{23, 19, 12, 4, 26, 8},{16, 7, 27, 20, 13, 2},{41, 52, 31, 37, 47, 55},{30, 40, 51, 45, 33, 48},{44, 49, 39, 56, 34, 53},{46, 42, 50, 36, 29, 32},}result : make([]byte, 6)// 将切片 d 中的所有元素逐个添加到切片 c 的末尾然后返回一个新的切片combined : append(c, d...)fmt.Println(combined: , combined)var bitcount 0 //用于统计result的比特位置var bittarget 0 //统计result放入的具体偏移量for i : 0; i 8; i {for j : 0; j 6; j {// 获取 表值-1 的真正的索引去cd合体的里面找bitIndex : pc2Table[i][j] - 1// 获取字节的索引byteIndex : bitIndex / 8// 根据byteIndex确定从combined中选取比特位所在的字节byteValue : combined[byteIndex]// 从combined特定字节bytevalue的特定比特位里取出 放入resultbittarget bitcount % 8result[bitcount/8] | (byteValue (1 (7 - (bitIndex % 8)))) (7 - (bitIndex % 8)) bittargetbitcount// 记录所有子密钥的步骤在上面subkey}}fmt.Println(本轮PC-2完成。)return result }// 3. 异或 func xorBytes(a, b []byte) []byte {if len(a) ! len(b) {panic(输入的两个字节切片长度不相等)}result : make([]byte, len(a))// fmt.Println(len(a), len(b))for i : range a {result[i] a[i] ^ b[i]}return result }// 4. S盒 6位变4位 func Sbox48To32(input []byte) []byte {if len(input) ! 6 {panic(Invalid input length for SBox48To32. Expected 6 bytes (48 bits).)}output : make([]byte, 4)var out uint32 0// 定义一个掩码用于提取6位数据块中的每一位const bitMask uint8 0x20// 遍历8个6位数据块for i : 0; i 8; i {// 提取当前6位数据块var b uint8for j : 0; j 6; j {// 根据当前循环的索引和位掩码从输入字节切片中提取相应的位bitIndex : (i*6 j) % 6// 按位或// 可以提取出 input[bitIndex] 字节中与 bitMask 对应的那一位。b | (input[bitIndex] bitMask) (7 - (j % 6))}// 计算行索引第1位和第6位r : (b1)1 (b 5)// 计算列索引第2到第5位c : ((b1)1)3 ((b2)1)2 ((b3)1)1 ((b 4) 1)// 从对应的S盒中获取值o : src.SBoxes[i][r][c]// 将获取的值设置到输出结果中按位或out | uint32(o) (i * 4)}// 将处理后的结果填充到输出切片for i : 0; i 4; i {output[i] byte((out (i * 8)) 0xff)}fmt.Printf(S盒结果%v\n, output)return output }// 5. P盒 func PboxExchange(input []byte) []byte {Pbox : [][]int{{16, 7, 20, 21},{29, 12, 28, 17},{1, 15, 23, 26},{5, 18, 31, 10},{2, 8, 24, 14},{32, 27, 3, 9},{19, 13, 30, 6},{22, 11, 4, 25},}if len(input) ! 4 {panic(Invalid input length for PboxExchange. Expected 4 bytes(32bits).)}// 将输入的字节切片转换为uint32类型var inputUint32 uint32for i, b : range input {inputUint32 | uint32(b) (uint32(i) * 8)}fmt.Println(转换为uint32后的输入值: , inputUint32)var out uint32 0for i : 0; i 8; i {for j : 0; j 4; j {index : Pbox[i][j] - 1bit : (inputUint32 uint32(31-index)) 1out | bit uint32(i*4j)}//fmt.Printf(经过第%d行Pbox置换操作后out的值十六进制: %x\n, i, out)}// 将置换后的结果转换为字节切片返回output : make([]byte, 4)for i : 0; i 4; i {output[i] byte((out (i * 8)) 0xff)}fmt.Println(P盒output: , output)return output }// 解密函数执行与加密相反的操作流程 func Decrypt(ciphertext []byte, subkeys [][]byte) []byte {fmt.Println(开始解密……)// 用于存储每组解密后的结果// 转换成字节切片组8个字节一组var cipherGroups [][]bytefor i : 0; i len(ciphertext); i 8 {endIndex : i 8if endIndex len(ciphertext) {endIndex len(ciphertext)}cipherGroups append(cipherGroups, []byte(ciphertext[i:endIndex]))}// 用于存储每组解密后的结果var decryptedGroups [][]bytefor _, group : range cipherGroups {println(开始初始置换)// 3. 填充明文 初始置换//paddedGroup : PadPlaintext(group)permutedText : InitialPermutation(group)println(初始置换完毕)// 4. 拆分L0和R0//println(开始拆分L0和R0)L, R : SplitLR(permutedText)println(拆分L0和R0完毕)// 5. 进行16轮加密for i : 0; i 16; i {// 扩展RexpandedR : Expand32To48(R)//println(扩展完毕)// 生成子密钥subkey : subkeys[15-i]// 异或xored : xorBytes(expandedR, subkey)//println(异或完毕)fmt.Printf(异或结果%v\n, xored)// S盒变换sboxed : Sbox48To32(xored)//println(S盒完毕)// P盒变换pboxed : PboxExchange(sboxed)//println(P盒完毕)// 与L异或newL : xorBytes(L, pboxed)//println(二次异或完毕)L RR newL}// 6. 合并L16和R16plaintext : MergeLR(L, R)// 7. 逆置换finalCiphertext : ReversePermutation(plaintext)decryptedGroups append(decryptedGroups, finalCiphertext)}// 将所有组的解密结果组合起来finalDecryptedText : []byte{}for _, decryptedGroup : range decryptedGroups {finalDecryptedText append(finalDecryptedText, decryptedGroup...)}return finalDecryptedText }func main() {println(请输入明文)reader : bufio.NewReader(os.Stdin)plaintextStr, err : reader.ReadString(\n)if err ! nil {fmt.Println(读取输入时出错, err)return}// 去除字符串末尾的换行符plaintextStr strings.TrimSpace(plaintextStr)// 转换成字节切片组8个字节一组var plainGroups [][]bytefor i : 0; i len(plaintextStr); i 8 {endIndex : i 8if endIndex len(plaintextStr) {endIndex len(plaintextStr)}plainGroups append(plainGroups, []byte(plaintextStr[i:endIndex]))}// 假设主密钥为8字节64位println(请输入密钥)reader bufio.NewReader(os.Stdin)keyyy, err : reader.ReadString(\n)if err ! nil {fmt.Println(读取输入时出错, err)return}// 去除字符串末尾的换行符keyStr : strings.TrimSpace(keyyy)key : []byte(keyStr)//key : []byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}println(开始填充密钥)// 1. 填充密钥如果需要newKey : PadKeyWithRandom(key)//println(填充结果, newKey)println(密钥填充结果)for _, b : range newKey {fmt.Printf(%02x , b)}println(\n开始生成子密钥……)// 2. 生成子密钥subkeys : GenerateSubkey(newKey)// 用于存储每组加密后的结果var encryptedGroups [][]bytefmt.Printf(明文字节组数%d\n, len(plainGroups))for _, group : range plainGroups {//println(len(group)) 不出意外是一个8一个3 因为This is DESprintln(开始初始置换)// 3. 明文填充 初始置换paddedGroup : PadPlaintext(group)permutedText : InitialPermutation(paddedGroup)println(初始置换完毕)// 4. 拆分L0和R0//println(开始拆分L0和R0)L, R : SplitLR(permutedText)println(拆分L0和R0完毕)// 5. 进行16轮加密for i : 0; i 16; i {// 扩展RexpandedR : Expand32To48(R)//println(扩展完毕)// 生成子密钥subkey : subkeys[i]// 异或xored : xorBytes(expandedR, subkey)//println(异或完毕)fmt.Printf(异或结果%v\n, xored)// S盒变换sboxed : Sbox48To32(xored)//println(S盒完毕)// P盒变换pboxed : PboxExchange(sboxed)//println(P盒完毕)// 与L异或newL : xorBytes(L, pboxed)//println(二次异或完毕)L RR newL}// 6. 合并L16和R16ciphertext : MergeLR(L, R)// 7. 逆置换finalCiphertext : ReversePermutation(ciphertext)encryptedGroups append(encryptedGroups, finalCiphertext)}// 将所有组的加密结果组合起来finalEncryptedText : []byte{}for _, encryptedGroup : range encryptedGroups {finalEncryptedText append(finalEncryptedText, encryptedGroup...)}// 调用解密函数进行解密验证decryptedText : Decrypt(finalEncryptedText, subkeys)fmt.Printf(明文解析字节内容%d\n, plainGroups)fmt.Printf(加密后的密文: %d\n, finalEncryptedText)fmt.Printf(解密后的明文: %d\n, decryptedText)/*// 示例用法data : []byte{0x12, 0x34, 0x56, 0x78}index : 3result : CircularLeftShift(data, index)fmt.Printf(原始数据: %x\n, data)fmt.Printf(循环左移后的结果: %x\n, result)*/ }
http://www.hkea.cn/news/14398649/

相关文章:

  • 重庆企业网络推广网站模板网站建设公司哪个好
  • 网站建设营改增深圳市城乡建设局网站
  • 淘客网站备案教程团员电子档案查询网
  • 如何免费制作企业网站公众号流量投放
  • 农产品电商网站的建设需求增加网站关键词库
  • wordpress制作电商网站做网站标配
  • 深圳建网站三千贵阳网站开发方舟网络
  • 专门做二手手机的网站有哪些wordpress 知更鸟
  • 天津最好的网站建设wordpress添加表单
  • 网站建设加盟模式山西教育平台网站建设
  • 韩城市住房和城乡建设局网站长春 网站 设计
  • 一个网站突然打不开杭州一起做网站
  • 美工培训网站如何做自己的网站链接
  • 做a视频网站广告图文制作用哪个软件
  • 在网站中加入锚链接应该怎么做分类信息网站怎么做SEO
  • 如何使用wordpress建站北京网站开发招聘
  • 企业网站备案要钱吗软件开发项目管理整个流程
  • 企业网站建设的三种方式邯郸做网站外包
  • 渭南中学校园网站建设工作汇报重庆营销策划公司排名
  • 免费二级网站网站建设与维护王欣
  • 跟我一起学做网站网页代码制作基础教程
  • 电商网站开发计划书网络推广方案百度百科
  • 青海最好的网站建设公司站长统计官方网站
  • 小说网站快速做排名企业推广策划书
  • 网站域名绑定破解建设一个网站报价
  • 网站开发报价合同东莞横沥新闻今天
  • 做网站建设的公司有哪些方面无锡市网站设计
  • 跨平台 移动网站开发大连网站建设联合企邦
  • ui设计公司网站技术成果交易网站建设方案
  • dw做网站的流程晋城网站建设