dongshi7433 2015-01-16 19:50
浏览 36
已采纳

Laravel 4加密:期望的字符数

I've just had an interesting little problem.

Using Laravel 4, I encrypt some entries before adding them to a db, including email address.

The db was setup with the default varchar length of 255.

I've just had an entry that encrypted to 309 characters, blowing up the encryption by cutting off the last 50-odd characters in the db.

I've (temporarily) fixed this by simply increasing the varchar length to 500, which should - in theory - cover me from this, but I want to be sure.

I'm not sure how the encryption works, but is there a way to tell what maximum character length to expect from the encrypt output for the sake of setting my database?

Should I change my field type from varchar to something else to ensure this doesn't happen again?

  • 写回答

2条回答 默认 最新

  • dongzhi4470 2015-01-17 13:25
    关注

    Conclusion

    First, be warned that there has been quite a few changes between 4.0.0 and 4.2.16 (which seems to be the latest version).

    The scheme starts with a staggering overhead of 188 characters for 4.2 and about 244 for 4.0 (given that I did not forget any newlines and such). So to be safe you will probably need in the order of 200 characters for 4.2 and 256 characters for 4.0 plus 1.8 times the plain text size, if the characters in the plaintext are encoded as single bytes.

    Analysis

    I just looked into the source code of Laravel 4.0 and Laravel 4.2 with regards to this function. Lets get into the size first:

    1. the data is serialized, so the encryption size depends on the size of the type of the value (which is probably a string);
    2. the serialized data is PKCS#7 padded using Rijndael 256 or AES, so that means adding 1 to 32 bytes or 1 to 16 bytes - depending on the use of 4.0 or 4.2;
    3. this data is encrypted with the key and an IV;
    4. both the ciphertext and IV are separately converted to base64;
    5. a HMAC using SHA-256 over the base64 encoded ciphertext is calculated, returning a lowercase hex string of 64 bytes
    6. then the ciphertext consists of base64_encode(json_encode(compact('iv', 'value', 'mac'))) (where the value is the base 64 ciphertext and mac is the HMAC value, of course).

    A string in PHP is serialized as s:<i>:"<s>"; where <i> is the size of the string, and <s> is the string (I'm presuming PHP platform encoding here with regards to the size). Note that I'm not 100% sure that Laravel doesn't use any wrapping around the string value, maybe somebody could clear that up for me.

    Calculation

    All in all, everything depends quite a lot on character encoding, and it would be rather dangerous for me to make a good estimation. Lets assume a 1:1 relation between byte and character for now (e.g. US-ASCII):

    1. serialization adds up to 9 characters for strings up to 999 characters
    2. padding adds up to 16 or 32 bytes, which we assume are characters too
    3. encryption keeps data the same size
    4. base64 in PHP creates ceil(len / 3) * 4 characters - but lets simplify that to (len * 4) / 3 + 4, the base 64 encoded IV is 44 characters
    5. the full HMAC is 64 characters
    6. the JSON encoding adds 3*5 characters for quotes and colons, plus 4 characters for braces and comma's around them, totaling 19 characters (I'm presuming json_encode does not end with a white space here, base 64 again adds the same overhead

    OK, so I'm getting a bit tired here, but you can see it at least twice expands the plaintext with base64 encoding. In the end it's a scheme that adds quite a lot of overhead; they could just have used base64(IV|ciphertext|mac) to seriously cut down on overhead.

    Notes

    • if you're not on 4.2 now, I would seriously consider upgrading to the latest version because 4.2 fixes quite a lot of security issues
    • the sample code uses a string as key, and it is unclear if it is easy to use bytes instead;
    • the documentation does warn against key sizes other than the Rijndael defaults, but forgets to mention string encoding issues;
    • padding is always performed, even if CTR mode is used, which kind of defeats the purpose;
    • Laravel pads using PKCS#7 padding, but as the serialization always seems to end with ;, that was not really necessary;
    • it's a nice thing to see authenticated encryption being used for database encryption (the IV wasn't used, fixed in 4.2).
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 Attention is all you need 的代码运行
  • ¥15 一个服务器已经有一个系统了如果用usb再装一个系统,原来的系统会被覆盖掉吗
  • ¥15 使用esm_msa1_t12_100M_UR50S蛋白质语言模型进行零样本预测时,终端显示出了sequence handled的进度条,但是并不出结果就自动终止回到命令提示行了是怎么回事:
  • ¥15 前置放大电路与功率放大电路相连放大倍数出现问题
  • ¥30 关于<main>标签页面跳转的问题
  • ¥80 部署运行web自动化项目
  • ¥15 腾讯云如何建立同一个项目中物模型之间的联系
  • ¥30 VMware 云桌面水印如何添加
  • ¥15 用ns3仿真出5G核心网网元
  • ¥15 matlab答疑 关于海上风电的爬坡事件检测