唐顺才-加解密算法实现(基础原理演示)
有一个做底端嵌入式的朋友请求帮忙做一个加密、解密的功能。 蓝牙一个广播包是32byte,因此不可能用rsa等加密算法。
这里用异或进行加密
加密、解密的本质思想是数据的可逆置换(军事上面的无线电密码本,就是置换符号)。 置换符号可以是静态、也可以是动态, 置换算法,是依据高等数学的对称曲线关系(x轴、y轴,或某个直线对称,即可实现加密、解密), 区别在于解密时cpu的计算时间,解密时cpu消耗的时间不一样。
本文是原理性质的讲解,本文作者也不擅长高等数学,因此用简单的加密方法,主要是讲清楚实现一个加密算法的原理。
一、c语言版本:
原理:
1 ^ 1 = 01 ^ 0 = 10 ^ 1 = 10 ^ 0 = 0
上代码:
#include #include #include // 密钥const unsigned char PUB[32] = { 0x01, 0x06, 0xa5, 0x5a, 0x79, 0xae, 0x1f, 0x7c, 0x02, 0x06, 0xa5, 0x5a, 0x79, 0xae, 0x1f, 0x7c, 0x03, 0x06, 0xa5, 0x5a, 0x79, 0xae, 0x1f, 0x7c, 0x04, 0x06, 0xa5, 0x5a, 0x79, 0xae, 0x1f, 0x7c,};// 加密、解密(加密、解密函数的实现,可以用其它对称曲线,例如椭圆曲线、抛物线进行加密)void en_de_cryption(unsigned char *data, int len, unsigned char *out) { unsigned char i = 0; for(i = 0; i < len; i++) { out[i] = data[i] ^ PUB[i]; }}int main(){ int i; // 原始数据 char p_data[16] = {"Hello World!"}; // buf存放解密、加密数据 char Encrypt1[16] = {0}, Decode1[16] = {0}; // 调用(奇数次)加密 en_de_cryption(p_data, strlen(p_data), Encrypt1); // 调用(偶数次)解密 en_de_cryption(Encrypt1, strlen(p_data), Decode1); // 打印原始数据、加密数据、解密数据 printf("Initial date: %s\n",p_data); printf("Encrypt1 date: %s\n",Encrypt1); printf("Decode1 date: %s\n",Decode1); return 0;}
执行效果:
root@jack-VirtualBox:~# ./a.out Initial date: Hello World!Encrypt1 date: IcǶHpj;Decode1 date: Hello World!root@jack-VirtualBox:~#
二、golang版本:
package mainimport "fmt"var PUB = [32]byte{ 0x01, 0x06, 0xa5, 0x5a, 0x79, 0xae, 0x1f, 0x7c, 0x02, 0x06, 0xa5, 0x5a, 0x79, 0xae, 0x1f, 0x7c, 0x03, 0x06, 0xa5, 0x5a, 0x79, 0xae, 0x1f, 0x7c, 0x04, 0x06, 0xa5, 0x5a, 0x79, 0xae, 0x1f, 0x7c,}func en_de_cryption(data []byte) []byte { for i, _ := range data { data[i] ^= PUB[i%32] } return data}func main() { data := []byte("hello world") fmt.Printf("%s\n", data) fmt.Printf("%s\n", en_de_cryption(data)) fmt.Printf("%s\n", en_de_cryption(data))}
运行:
三、golang版本-文件加密、文件解密:
文件加密,就需要在加密文件中写入必要的状态信息、公钥等信息:
加密文件的存储格式为:加密头的length(4byte)、加密头(512-4) byte、密文
先简单设计,后面有空对完整性、性能进行优化,然后实现一点业务功能(例如结合网络传输协议对内容快速加密、对象存储底层加密)
package mainimport ("crypto/sha256""encoding/json""errors""io""os""path/filepath""reflect")var PUB = [32]byte{0x01, 0x06, 0xa5, 0x5a, 0x79, 0xae, 0x1f, 0x7c,0x02, 0x06, 0xa5, 0x5a, 0x79, 0xae, 0x1f, 0x7c,0x03, 0x06, 0xa5, 0x5a, 0x79, 0xae, 0x1f, 0x7c,0x04, 0x06, 0xa5, 0x5a, 0x79, 0xae, 0x1f, 0x7c,}type header struct {Magic uint64 `json:"magic"`Length int64 `json:"length"`Sha256 [32]byte `json:"sha256"`RawName stringnb intnp intpub []bytereader io.Reader}func (h *header) Read(p []byte) (n int, err error) {h.reader.Read(p)h.np = h.nbfor i, _ := range p {p[i] ^= h.pub[h.np%32]h.np += 1}return int(h.np - h.nb), nil}func en_de_cryption(data []byte) []byte {for i, _ := range data {data[i] ^= PUB[i%32]}return data}func file_en_cryption(path string, key string) ([]byte, error) {f, err := os.Open(path)if err != nil {return nil, err}defer f.Close()header := &header{Magic: 0xbadbeef0, pub: []byte(key)}header.Sha256 = sha256.Sum256([]byte(key))header.RawName = filepath.Base(path)if fileinfo, err := f.Stat(); err == nil {header.Length = fileinfo.Size()} else {return nil, err}tempFile := os.File{}defer func() {tempFile.Close()}()if File, err := os.CreateTemp("", path+".tscz"); err == nil {defer func() {File.Close()}()if data, err := json.Marshal(header); err == nil {metadataLength := len(data)metadataBuf := make([]byte, 4)metadataBuf[0] = byte(metadataLength & 0xff)metadataBuf[1] = byte(metadataLength >> 8 & 0xff)metadataBuf[2] = byte(metadataLength >> 16 & 0xff)metadataBuf[3] = byte(metadataLength >> 24 & 0xff)File.Write(metadataBuf)buffer := make([]byte, 512-4)copy(buffer, data)File.Write(buffer)}s := make([]byte, 4096)for {if nr, err := f.Read(s[:]); err == nil && nr > 0 {// 打印原始数据//fmt.Println(string(s))s = s[:nr]header.np = header.nbfor i, _ := range s {s[i] ^= header.pub[header.np%len(header.pub)]header.np += 1}File.Write(s)} else {break}}os.Rename(File.Name(), path+".tscz")}return nil, nil}func SliceEquals(a, b interface{}) bool {// a,有任意一个不是slice返回false_a := reflect.ValueOf(a)_b := reflect.ValueOf(b)// 长度不等则两个slice不同if _a.Len() != _b.Len() {return false}// 依次比较每个值for i := 0; i < _a.Len(); i++ {if _a.Index(i).Interface() != _b.Index(i).Interface() {return false}}return true}func file_de_cryption(path string, key string) ([]byte, error) {if filepath.Ext(path) != ".tscz" {return nil, errors.New("ext name of de cryption should be .tscz")}f, err := os.Open(path)if err != nil {return nil, err}defer f.Close()header := &header{pub: []byte(key)}buf := make([]byte, 512)if n, err := f.Read(buf); err == nil && n > 0 {metadataLength := buf[0] | buf[1]<<8 | buf[2]<<16 | buf[3]<<24if err := json.Unmarshal(buf[4:4+metadataLength], &header); err != nil {return nil, err}} else {return nil, err}if header.Magic != 0xbadbeef0 {return nil, errors.New("unidentified by this tool")}if !SliceEquals(header.Sha256, sha256.Sum256([]byte(key))) {return nil, errors.New("invalid password")}tempFile := os.File{}defer func() {tempFile.Close()}()if File, err := os.CreateTemp("", path); err == nil {defer func() {File.Close()}()f.Seek(512, os.SEEK_SET)s := make([]byte, 4096)for {if nr, err := f.Read(s[:]); err == nil && nr > 0 {s = s[:nr]header.np = header.nbfor i, _ := range s {s[i] ^= header.pub[header.np%len(header.pub)]header.np += 1}File.Write(s)// 打印解密后的数据//fmt.Println(string(s))} else {break}}os.Rename(File.Name(), header.RawName+".bak")}return nil, nil}func main() {// 数据加密、解密//data := []byte("hello world")//fmt.Printf("%s\n", data)//fmt.Printf("%s\n", en_de_cryption(data))//fmt.Printf("%s\n", en_de_cryption(data))// 文件加密、解密file_en_cryption("file.txt", "nihao")file_de_cryption("file.txt.tscz", "nihao")}
效果: