AES过程

来源:互联网 发布:练六级英语听力的软件 编辑:程序博客网 时间:2024/05/29 09:29
  1. 分块密码, 因此要求被加密对象长度为块长度的倍数
  2. 秘钥长度必须是16或者24或者32 分别对应AES-128, AES-192, AES-256
  3. 需要以某种形式将明文的长度编码
  4. 加密算法有cipher.NewCBCEncrypter, cipher.NewCFBEncrypter, 但是他们返回的对象分别是Block和Stream。 未比较块和流的优点缺点。

只要理解了这个过程代码非常好调。

package mainimport (    "bytes"    "crypto/aes"    "crypto/cipher"    "crypto/rand"    "encoding/binary"    "fmt"    "io"    "unsafe")// PCKS paddingfunc padKey(key []byte) []byte {    var targetKeySize = 16    if len(key) <= 16 {        targetKeySize = 16    } else if len(key) <= 24 {        targetKeySize = 24    } else {        targetKeySize = 32    }    if r := targetKeySize - len(key); r > 0 {        nkey := make([]byte, targetKeySize)        copy(nkey, key)        copy(nkey[len(key):], bytes.Repeat([]byte{byte(r)}, r))        key = nkey    }    return key[:targetKeySize]}func encrypt(source []byte, keyStr string) ([]byte, error) {    srcLength := len(source)    var usize uint64    headSize := int(unsafe.Sizeof(usize))    head := make([]byte, headSize, headSize+len(source))    source = append(head, source...)    len0 := len(source)    if r := len0 % aes.BlockSize; r > 0 {        len0 += aes.BlockSize - r        padding := make([]byte, aes.BlockSize-r)        if _, err := io.ReadFull(rand.Reader, padding); err != nil {            return nil, err        }        source = append(source, padding...)    }    buffer := make([]byte, len0+aes.BlockSize)    iv := buffer[:aes.BlockSize]    if _, err := io.ReadFull(rand.Reader, iv); err != nil {        return nil, err    }    usize = uint64(srcLength)    binary.BigEndian.PutUint64(source, usize)    block, ec := aes.NewCipher(padKey([]byte(keyStr)))    if ec != nil {        return nil, ec    }    mode := cipher.NewCBCEncrypter(block, iv)    mode.CryptBlocks(buffer[aes.BlockSize:], source)    return buffer, nil}func decrypt(encbuffer []byte, keyStr string) ([]byte, error) {    iv := encbuffer[:aes.BlockSize]    out := encbuffer[aes.BlockSize:]    block, ec := aes.NewCipher(padKey([]byte(keyStr)))    if ec != nil {        return nil, ec    }    mode := cipher.NewCBCDecrypter(block, iv)    mode.CryptBlocks(out, out)    usize := binary.BigEndian.Uint64(out)    var headSize = int(unsafe.Sizeof(usize))    return out[headSize : headSize+int(usize)], nil}func encTest(src, key string) {    ebuff, err := encrypt([]byte(src), key)    if err != nil {        panic(err)    }    dbuff, err := decrypt(ebuff, key)    if err != nil {        panic(err)    }    fmt.Printf("<%v> : len = %v (encrypted length=%v)\n",        string(dbuff),        len(dbuff),        len(ebuff),    )    fmt.Printf("<%v>\n", ebuff)}func main() {    src := []byte("hasta victoria siempre")    encrypted, err := encrypt(src, "klo")    if err != nil {        panic(err)    }    fmt.Printf("%v\n", encrypted)    fmt.Printf("len for encrypted: %v\n", len(encrypted))    decrypted, err := decrypt(encrypted, "klo")    if err != nil {        panic(err)    }    fmt.Printf("decrypted len is: %v\n", len(decrypted))    fmt.Printf("decrypted: %v\n", string(decrypted))    encTest("", "a")    encTest("", "ss")    encTest("a", "")    encTest("a", "aa")}

reference link:
https://stackoverflow.com/questions/24072026/golang-aes-ecb-encryption
https://stackoverflow.com/questions/18817336/golang-encrypting-a-string-with-aes-and-base64
https://www.ctolib.com/topics-3631.html
http://www.cnblogs.com/lianghui66/archive/2013/03/07/2948494.html
http://gunn.me/2015/07/213/
http://www.cnblogs.com/lavin/p/5373188.html
https://segmentfault.com/a/1190000004151272

https://crypto.stackexchange.com/questions/20941/why-shouldnt-i-use-ecb-encryption/20946#20946
http://www.cnblogs.com/happyhippy/archive/2006/12/23/601357.html
https://baike.baidu.com/item/Diffie-Hellman

最后附上nodejs(其他工具的实现)

const crypto = require('crypto');const assert = require('assert');//bufffunction padKey(buffStr){    let buffKey = Buffer.from(buffStr);    let targetLen = 16;    if(buffKey.length<=16){        targetLen = 16;    } else if(buffKey.length<=24){        targetLen = 24;    } else {        targetLen = 32;    }    let r = targetLen - buffKey.length;    if (r>0) {        let padding = Buffer.alloc(r, r);        buffKey = Buffer.concat([buffKey, padding]);    }    return buffKey.slice(0, targetLen);}function randInt8(){    return Math.floor(Math.random() * 256);}/// a buffer of length equals block-sizefunction randIv() {    let rv = Buffer.alloc(16, 0);    rv.forEach((c,i)=>{        rv[i] = randInt8();    });    return rv;}function makeCipherName(k){    let cipherName = 'aes-128-cbc';  //cipher block chain    switch(k.length){    case 16:        cipherName = 'aes-128-cbc';        break;    case 24:        cipherName = 'aes-192-cbc';        break;    case 32:        cipherName = 'aes-256-cbc';        break;    default:        throw new Error(`unknown key length ${k.length}`);    }    return cipherName;}function makeCipher(k, iv){    let algoName = makeCipherName(k);    return crypto.createCipheriv(algoName, k, iv);}function makeDecipher(k, iv){    let algoName = makeCipherName(k);    return crypto.createDecipheriv(algoName, k, iv);}// using uint64 as the headfunction encrypt(source, keyStr){    let srcBuff = Buffer.from(source);    let headBuff = Buffer.alloc(8, 0)    headBuff.writeUInt32BE(srcBuff.length, 4);    srcBuff = Buffer.concat([headBuff, srcBuff]);    let r = srcBuff.length % 16;    if(r>0){        srcPadding = Buffer.alloc(16 - r, 0);        srcPadding.forEach((c,i)=>{srcPadding[i] = randInt8()});    }    let startiv = randIv();    let cipher = makeCipher(padKey(keyStr), startiv);    let buffs = [startiv];    buffs.push(cipher.update(srcBuff));    buffs.push(cipher.final());    return Buffer.concat(buffs);}function decrypt(chunk, keyStr){    if(Buffer.isBuffer(chunk)){        //nada    } else {        chunk = Buffer.from(chunk, 'hex');    }    //console.log("tot length is(encoded): %s", chunk.length);    let iv = chunk.slice(0, 16)    chunk = chunk.slice(16);    let cipher = makeDecipher(padKey(keyStr), iv);    let decoded = [];    decoded.push(cipher.update(chunk));    decoded.push(cipher.final());    decoded = Buffer.concat(decoded);    //console.log("decoded length is %s", decoded.length);    let len = decoded.readUInt32BE(4);    return decoded.slice(8, 8+len);}if(process.argv.length<4){    console.error("not enough parameters");    process.exit(-1);}//console.log(encrypt('hasta victoria siempre', 'kl1'));let encrypted = encrypt(process.argv[2], process.argv[3]);console.log(encrypted.toString('hex'));console.log(encrypted.toString('utf8'));let decrypted = decrypt(encrypted, process.argv[3]);console.log(decrypted.toString());