我正在将一些加密软件移植到 Common Lisp 中。这是我用多种其他语言做过的练习。它需要 UTF-8 字符串的 Base64 编码,包括非 ASCII 字符。我的第一个单元测试使用字符串“abcd£”检查这一点。 Base64 的预期值为“YWJjZMKj”。 (我也在 https://www.base64encode.org/ 上检查了这一点)。我尝试过两个 lisp 包,cl-base64 和 base64,每个都返回“YWJjZKM=”。
我在 Windows 10 上运行 sbcl 2.3.2。:SB-UNICODE 位于 FEATURES 列表中。我已经尝试过 cl-base64 提供的字符串和 usb8 数组。这是我的五点测试:
(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,或者根本没有正确处理 UTF-8。特别是假设
stdutils
是 this 那么它的 string-to-usb8-array
是
(defun-exported string-to-usb8-array (str)
(declare (simple-string str))
(let* ((len (length str))
(vec (make-usb8-array len)))
(declare (fixnum len)
(type (simple-array (unsigned-byte 8) (*)) vec)
(optimize (speed 3)))
(do ((i 0 (1+ i)))
((= i len) vec)
(declare (fixnum i))
(setf (aref vec i) (char-code (schar str i))))))
它甚至没有尝试处理 UTF-8。巧合的是,它“有效”,因为
#\£
的字符代码小于 256。
我没有检查过其他案例,但我确定是一样的。
如果您需要对字符串的 UTF-8 表示形式进行 Base64 编码,您需要确保将其转换为 UTF-8 编码,或者 Base64 编码器会为您完成此操作。特别是,CL 中不存在“UTF-8 字符串”这样的东西:CL 字符串是字符向量,而不是八位位组向量,八位位组是这些字符的某种编码。 (如果您已经知道这一点,我们深表歉意。)