dongmou3615
2018-06-08 13:42
浏览 303
已采纳

AES-256-CBC加密在golang和node / php之间不匹配

I've been having a bit of problems trying to figure out why my encryption is different in go compared to php and node. I was hoping someone could help me figure out the differences. Let's assume this is the data:

plaintext: hello big worldshello big worlds

key: jJr44P3WSM5F8AC573racFpzU5zj7Rg5

iv: 97iEhhtgVjoVwdUw

Here are the resulting encryptions in base64:

Node and PHP return :

OTdpRWhodGdWam9Wd2RVd0OgJ+Z7pSCVioYq41721jarxqLKXN3PcnnY6/AOrHeEfsTxXfCgm2uUi+vmCAdpvw==

Go returns:

OTdpRWhodGdWam9Wd2RVd0OgJ+Z7pSCVioYq41721jarxqLKXN3PcnnY6/AOrHeE

As you can see they're almost identical and its been driving me crazy. Could you guys take quick look at the encryption code below and give me hints on what the problem could be?

GO:

func EncryptString(plainstring string, keystring string, encFormat int, ivOverride bool) (string) {
    // Load your secret key from a safe place and reuse it across multiple
    // NewCipher calls. (Obviously don't use this example key for anything
    // real.) If you want to convert a passphrase to a key, use a suitable
    // package like bcrypt or scrypt.
    key := []byte(keystring)
    plaintext := []byte(plainstring)

    // CBC mode works on blocks so plaintexts may need to be padded to the
    // next whole block. For an example of such padding, see
    // https://tools.ietf.org/html/rfc5246#section-6.2.3.2. Here we'll
    // assume that the plaintext is already of the correct length.
    if len(plaintext)%aes.BlockSize != 0 {
        panic("plaintext is not a multiple of the block size")
    }

    block, err := aes.NewCipher(key)
    if err != nil {
        panic(err)
    }

    // The IV needs to be unique, but not secure. Therefore it's common to
    // include it at the beginning of the ciphertext.
    ciphertext := make([]byte, aes.BlockSize+len(plaintext))
    iv := ciphertext[:aes.BlockSize]
    if _, err := io.ReadFull(bytes.NewReader([]byte("97iEhhtgVjoVwdUw")), iv); err != nil {
       panic(err)
    }

    mode := cipher.NewCBCEncrypter(block, iv)
    mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)

    // It's important to remember that ciphertexts must be authenticated
    // (i.e. by using crypto/hmac) as well as being encrypted in order to
    // be secure.

    return base64.StdEncoding.EncodeToString(ciphertext)
}

NODE:

encryptString: function(string, key, fmt = null, ivOverride = false) {
    // Build an initialisation vector
    let iv;
    if(!ivOverride) {
        iv = crypto.randomBytes(IV_NUM_BYTES).toString('hex').slice(0,16);
    } else {
        iv = IV_OVERRIDE_VALUE; //97iEhhtgVjoVwdUw
    }
    // and encrypt
    let encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let encryptedData = encryptor.update(string, 'utf8', 'binary') + encryptor.final('binary');
    encryptedData = iv+''+encryptedData;
    encryptedData = Buffer.from(encryptedData, 'binary').toString('base64');

    return encryptedData;
}

I've noticed that removing encryptor.final('binary') makes the two result in the same encryption but php does not have the .final() thing going for it. Php uses open_ssl_encrypt() which seems to have this built in. Is there a way to add an equivalent in go? Looking for advice. Thanks

  • 写回答
  • 好问题 提建议
  • 追加酬金
  • 关注问题
  • 邀请回答

1条回答 默认 最新

相关推荐 更多相似问题