返回顶部
首页 > 资讯 > 后端开发 > GO >golang与php的openssl_encrypt加解密
  • 111
分享到

golang与php的openssl_encrypt加解密

phpgolang 2023-09-03 10:09:22 111人浏览 八月长安
摘要

PHP中openssl_encrypt加密函数 在PHP(PHP 5 >= 5.3.0, php 7, PHP 8)中,openssl_encrypt的参数大致如下: openssl_encrypt( string $data,

PHP中openssl_encrypt加密函数

在PHP(PHP 5 >= 5.3.0, php 7, PHP 8)中,openssl_encrypt的参数大致如下:

openssl_encrypt(    string $data,    string $cipher_alGo,    string $passphrase,    int $options = 0,    string $iv = "",    string &$tag = null,    string $aad = "",    int $tag_length = 16): string|false
  • $data为待加密的数据字符串
  • $cipher_algo为加密算法,如aes-128-ecb,中间这个数字表示密钥长度为128位。所有加密算法可通过openssl_get_cipher_methods获得。
  • $passphrase为密钥。既然上面的算法都规定了密钥长度,那这个密钥的字符串长度就已经确定下来了。但PHP随性的一点是如果密钥小于或超过算法指定的长度,也都能正常返回加密结果,而不像Java等语言直接抛出密钥长度不正确的异常。根据手册解释:
若 passphrase 比预期长度短,将静默用 NUL 填充; 若比预期长度更长,将静默截断。

查了PHP源代码下的openssl实现,找到如下

if (key_len > passWord_len) {  if ((OPENSSL_DONT_ZERO_PAD_KEY & options) && !EVP_CIPHER_CTX_set_key_length(cipher_ctx, password_len)) {      php_openssl_store_errors();      php_error_docref(NULL, E_WARNING, "Key length cannot be set for the cipher algorithm");      return FaiLURE;  }  key = emalloc(key_len);  memset(key, 0, key_len);   memcpy(key, *ppassword, password_len);  *ppassword = (char *) key;  *ppassword_len = key_len;  *free_password = 1;}
  • memset(key, 0, key_len); 应该对应的就是ASCII中的零,也就是PHP里的chr(0)。所以如果一个密钥长度不够,PHP会自动在密钥后面用chr(0)不足。例如:aes-128-ecb算法,密钥长度应为128位,也就是字符串长度为16。这时如果密钥为"1234567890abcde"和"1234567890abcde".chr(0)的意义是一样的,得到的加密结果也是一样的。至于超出长度自动截断,这应该很好理解了。

  • $options 是以下标记的按位或: OPENSSL_RAW_DATA、 OPENSSL_ZERO_PADDING, 指定对于数据,如何填充的。
    其中OPENSSL_RAW_DATA的含义应该是不经过base64_encode,即raw data。如果没有这个掩码,则会返回base64字符串。
    而默认的填充是PKCS#7。经过查询,OPENSSL_ZERO_PADDING这个选项在PHP新版本(7.4.4),已经被废弃了,效果跟OPENSSL_NO_PADDING效果一样。

0 : 默认值,PKCS#7进行填充, 返回的数据经过 base64 编码;1 : OPENSSL_RAW_DATA, PKCS#7进行填充, 但返回的结果未经过 base64 编码;2 : OPENSSL_ZERO_PADDING, openssl不推荐chr(0)填充的方式, 需要开发者自行填充, 返回的结果经过 base64 编码;3 : OPENSSL_NO_PADDING, 需要开发者自行填充, 返回的结果不经过base64编码;
  • $iv 初始向量(Initialization Vector),不同的IV加密后的字符串是不同的,加密和解密需要相同的IV,既然IV看起来和key一样,却还要多一个IV的目的,对于每个块来说,key是不变的,但是只有第一个块的IV是用户提供的,其他块IV都是自动生成。 IV的长度为16字节。 超过或者不足,可能实现的库都会进行补齐或截断。ECB方式不需要iv,所以之前以ECB举例也是为了快速上手。

  • $tag 使用 AEAD 密码模式(GCM 或 CCM)时传引用的验证标签。

  • $aad 附加的验证数据。

  • $tag_length 验证 tag 的长度。GCM 模式时,它的范围是 4 到 16。

go中解密

  • php中key和iv的长度不足也能加密成功,go中则不行,解密起来比较坑
  • 针对AES-128-CBC、AES-256-CBC两种加密方式,我们进行的转换

引用go相关包

"GitHub.com/wumansgy/goEncrypt/aes"

php加密

$plain = "hello world";$key = "abcdef1234567890";$iv = "1234567890abcdef";$aesPassword = openssl_encrypt($plain, "AES-128-CBC", $key, OPENSSL_RAW_DATA, $iv);$encryptAesPasswords = base64_encode($aesPassword);

go解密

func AesEncrypt() {originData := "CtqXZg7SH5ACIK7gWwOu4w=="iv := []byte("1234567890abcdef")key := "abcdef1234567890"        //AES-128-CBC长度是16,AES-256-CBC长度为32,iv固定长度为16secreTKEy := aesCbcKeyIvPadding(key, 16)str, err := aes2.AesCbcDecryptByBase64(originData, secretKey, iv)if err != nil {fmt.Println(err)}fmt.Println(string(str))}func aesCbcKeyIvPadding(src string, aesLen uint8) []byte {srcByte := make([]byte, aesLen)srcByteTemp := []byte(src)for i := 0; i < len(srcByteTemp); i++ {srcByte[i] = srcByteTemp[i]}return srcByte}

来源地址:https://blog.csdn.net/baidu_28393027/article/details/127782861

您可能感兴趣的文档:

--结束END--

本文标题: golang与php的openssl_encrypt加解密

本文链接: https://lsjlt.com/news/391960.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作