Common Lisp中非ASCII字符Base64编码结果不符问题求助
Common Lisp中UTF-8字符串Base64编码结果不符问题
我正在将加密软件移植到Common Lisp,需对包含非ASCII字符的UTF-8字符串进行Base64编码。使用测试字符串“abcd£”时,预期Base64结果为“YWJjZMKj”,但cl-base64与base64包均返回“YWJjZKM=”。
运行环境为Windows 10下的SBCL 2.3.2,:SB-UNICODE已在*FEATURES*列表中。尝试了直接传入字符串、使用cl-base64提供的USB8数组两种方式,以下是FiveAM测试代码及失败输出:
测试代码
(in-package :rsearch-tests) (def-suite test-encryption :description "test encryption functions") (in-suite test-encryption) (test feature (is-true (member :sb-unicode *features*) t)) (test base64-1 (is (string= "YWJjZMKj" (cl-base64:string-to-base64-string "abcd£")))) (test base64-3 (is (string= "YWJjZMKj" (cl-base64:usb8-array-to-base64-string (stdutils:string-to-usb8-array "abcd£")))))
测试输出
Running test suite TEST-ENCRYPTION Running test FEATURE . Running test BASE64-1 f Running test BASE64-2 f Did 3 checks. Pass: 1 (33%) Skip: 0 ( 0%) Fail: 2 (66%) Failure Details: -------------------------------- BASE64-2 in TEST-ENCRYPTION []: (CL-BASE64:USB8-ARRAY-TO-BASE64-STRING (STDUTILS:STRING-TO-USB8-ARRAY "abcd£")) evaluated to "YWJjZKM=" which is not STRING= to "YWJjZMKj" -------------------------------- -------------------------------- BASE64-1 in TEST-ENCRYPTION []: (CL-BASE64:STRING-TO-BASE64-STRING "abcd£") evaluated to "YWJjZKM=" which is not STRING= to "YWJjZMKj" --------------------------------
问题原因
核心问题在于字符£的编码处理:
£的标准UTF-8编码是三个字节(0xC2 0xA3),加上前面的"abcd"四个字节,总字节数为6,Base64编码后正好是8个字符,无需填充,对应预期结果YWJjZMKj。- 而实际得到的
YWJjZKM=是7个字符加一个填充=,说明代码中把£当成了单字节编码(比如Windows-1252编码的0xA3),总字节数变成5,导致Base64编码需要填充。
这种情况要么是stdutils:string-to-usb8-array默认使用了系统本地编码(而非UTF-8),要么是cl-base64:string-to-base64-string没有指定UTF-8作为外部格式。
解决方法
使用SBCL自带函数确保UTF-8编码
用sb-ext:string-to-octets显式指定UTF-8编码字符串为字节数组,再传入cl-base64处理:(cl-base64:usb8-array-to-base64-string (sb-ext:string-to-octets "abcd£" :external-format :utf-8))给cl-base64指定UTF-8外部格式
调用cl-base64:string-to-base64-string时,显式传入:external-format :utf-8参数:(cl-base64:string-to-base64-string "abcd£" :external-format :utf-8)检查stdutils函数的编码逻辑
若必须使用stdutils:string-to-usb8-array,需确认其实现是否支持指定UTF-8编码,或修改其默认编码为UTF-8。
内容的提问来源于stack exchange,提问作者jsparkes
相关产品推荐
相关产品推荐

