时间:2021-05-20
起因
最近遇到一个问题,把某个字符串计算MD5,之后把该字符串加密与MD5一起上传到服务端,服务端解密后重新计算md5发现与上传的MD5不一致,而出问题的字符串中无一例外都有Emoji表情。但我自己弄个带表情的字符串上传却没有什么问题。
最终确认这是在Android 5.1以下 jstring -> char数组 时出的问题。下面通过一个示例来还原这个过程。
事件还原
假设有一个字符串s,String s = "\uD83D\uDC8B"; ,对应表情💋。通过调用getBytes()方法,会看到对应的byte数组为[-16, -97, -110, -117] ,按16进制输出为[f0, 9f, 92, 8b] 。
定义一个参数为String的native方法,public native String test(String str); ,在对应的C/C++代码中,通过env->GetStringUTFChars获取传入的String对应的char数组,把char数组的每一个元素按16进制输出。
在Android 7.1.2的测试机上,native层输出的结果为[f0, 9f, 92, 8b] ,与Java的byte数组是一样的,但是在Android 4.4.4的测试机上,输出结果为[ed, a0, bd, ed, b2, 8b] 。从而导致加密后的结果不一样。
服务端收到旧版Android的数据解密后得到[ed, a0, bd, ed, b2, 8b] ,计算MD5自然无法与[f0, 9f, 92, 8b]计算MD5一样。
Unicode、UTF-8、UTF-16
可能有人不是很清楚上面那2种byte数组是怎么来的。首先我们要知道,UTF-8和UTF-16都是Unicode的实现。\uD83D\uDC8B其实是UTF-16大端的表现形式,对于大于0xFFFF(0x10000~0x10FFFF)的Unicode,转换为UTF-16的步骤如下:
按照这个步骤反推:
所以,表情💋对应的Unicode为0x1F48B。
UTF-8的规则是,对于占N个字节的符号(N>1),第一个字节前N位都是1,N+1位是0,后面的字节前2位为10,然后把Unicode的二进制位填入空缺的二进制位中,空出的位置补0。因此,上面的Unicode 0x1F48B转为UTF-8需要占4个字节,为:
11110 000
10 011111
10 010010
10 001011
即0xF09F928B,这也就是[f0, 9f, 92, 8b]这个byte数组的由来。
那么[ed, a0, bd, ed, b2, 8b]这个byte数组又是怎么来的呢?这是把\uD83D\uDC8B当成2个单独的字符处理了,按照上面Unicode转UTF-8的逻辑,Unicode 0xD83D转为UTF-8为1110 1101 10 100000 10 111101,即0xEDA0BD,Unicode 0xDC8B转为UTF-8为1110 1101 10 110010 10 001011,即0xEDB28B。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
最近有Mac用户发现mac存在跨平台字体兼容性问题,那么mac跨平台字体兼容性问题怎么解决呢?跟着小编一起来看看mac跨平台字体兼容性问题解决方案。mac跨平台
近日,光速手机输入法Android平台更新至1.1.0版本,本次升级主要新增了emoji表情和夜间皮肤功能。新增emoji表情Emoji是目前非常流行的一种表情
解决浏览器兼容性问题,首先要把设计语言升级到最新的版本,通常最新的CMS都遵循HT-ML5、CSS3等最新的技术标准,很大程度上减少了兼容性问题的产生。另外,在
正确认识AGP接口的兼容性问题对解决因接口兼容性问题导致的故障很有意义。简单说AGP8X规格与旧有的AGP1X/2X模式不兼容,大多数AGP4X显卡则可以兼
前言随着小程序的热度不减,更多的电商大佬来时使用小程序,在微信小程序开发中,经常会遇到一些兼容性的问题,下面这篇文章就记录下在微信小程序中遇到的一些兼容性问题,