【发布时间】:2019-06-13 14:39:37
【问题描述】:
我想创建一个凯撒密码,它可以对整个 Unicode(私人使用区域除外)中的 Unicode 可打印字符(单和多码点字素簇、表情符号等)进行编码/解码。最好是使用所有可打印字符的列表。
注意:尽管我想创建一个凯撒密码,但这实际上与加密无关。问题是关于调查 unicode 的属性。
我发现了这些问题:
What is the range of Unicode Printable Characters?
Cipher with all unicode characters
但我没有得到我想要的答案。
注意: 如果您给出编码答案,我最感兴趣的解决方案是 使用 python3 或 perl6,因为它们是我的主要语言。
最近,我接到了一项任务,要编写凯撒密码,然后对英文文本进行编码和解码。
我通过使用字符串库的内置 string.printable 常量在 python 中解决了它。这是常量的打印输出: (我使用了 Visual Studio 代码)
[查看下面的python代码和结果]
文档说: ''' 被认为是可打印的 ASCII 字符串。这是数字、ascii_letters、标点符号和空格的组合。 ''' https://docs.python.org/3.6/library/string.html#string-constants
我想知道如何创建一个凯撒密码,该密码可以编码/解码您可以从 unicode 代码点生成的所有可能的可打印字符(假设您拥有所有必要的字体来查看那些应该在屏幕上可见的字体)。 H1>
这是我对它的含义的理解 可以打印的字符:
当我取上面的python字符串常量时, 并用左或右箭头键遍历它 在键盘上,我需要 100 次敲击才能得到 到最后(与字符数相同)。 好像有一对一的 可打印之间的对应关系 字符,并且可以一键遍历。
现在考虑这个字符串:
"????????????????????ij क्षि ????”
基于pythons string.printable 常量, 在我看来,这个字符串由 以下 7 个可打印字符: (您可以在以下位置查找各个代码点:https://unicode-table.com/en/)
1(家庭)2(拉丁文小连字 Ij) 3(回车) 4(天城文 kshi) 5(空格) 6(零宽度不间断空格) 7(黑桃 A)
???????????????? 代码点:128104 8205 128105 8205 128103 8205 128102 (参考:https://emojipedia.org/family-man-woman-girl-boy/)
(拉丁文小连字 Ij) ij 代码点:307
(回车) 代码点:13
(天城文 kshi)
क्षि
代码点:2325 2381 2359 2367
(见本页:http://unicode.org/reports/tr29/)
(代码点似乎是十六进制而不是数字)
(空格) 代码点:32
(零宽度不间断空格) 代码点:65279 (又名 U+FEFF 字节顺序标记 (BOM)) (https://en.wikipedia.org/wiki/Byte_order_mark)
(扑克牌黑桃 A) ??? 代码点:127137
当我粘贴这个 将字符串输入记事本,并尝试用箭头键遍历它, 我最终使用了 10 个击键而不是 7 个, 因为家庭表情符号需要 4 击键 (可能是因为记事本无法处理零宽度连接器, 代码点:8205,当然记事本不能显示家族字形)。 另一方面,当我将字符串发布到谷歌搜索时, 我可以用 7 笔遍历整个字符串。
然后我尝试创建字符串 在 Perl6 中看看 Perl6 的字形是什么 意识会使字符串:
(我使用 Atom 编辑器)
[参见下面的 perl6 代码和结果]
perl6 认为梵文 kshi 字符 क्षि (4 个代码点) 实际上是 2 个字素,每个字素有 2 个代码点。 即使它可以表示为两个字符, 如上面的列表所示, 我认为这是一个错误。 Perl6 应该是字素 知道,甚至我的 Windows 记事本(和谷歌搜索) 认为它是单个字素/字符。
基于 2 个字符串, 的实际定义 一个可打印的字符似乎是这样的: '它是可以遍历的 unicode 代码点的任意组合 只需按一下键盘上的向左或向右箭头键 理想情况下”。
“在理想情况下”意味着 你正在使用的环境,可以这么说, 像谷歌搜索一样: 也就是说,它识别例如一个表情符号 (4 人家庭)或字素簇 (梵文字符) 作为一个可打印的字符。
3 个问题:
1: 以上是对它的含义的公平定义吗 成为 unicode 中的可打印字符?
2: 不管你是否接受这个定义, 你知道任何可打印字符的列表吗 涵盖当前使用的 unicode 平面和可能的 字形簇,而不仅仅是 100 个 ASCII 字符 python字符串库有 (如果我有这样的列表,我想我可以创建一个密码 很容易)?
3: 鉴于这样的列表不存在,并且您 接受定义, 您将如何创建这样一个列表 我可以创造一个凯撒密码 可以加密任何/所有可打印的 给定以下 4 个条件的字符?
注意:这 4 个条件只是 我想象的需要一个适当的 凯撒密码。
条件a
要加密的字符串将 是一个由标准组成的有效 utf8 字符串 unicode 代码点(没有未分配或私人使用区域 代码点)
条件b
加密的字符串也必须是有效的 由标准组成的 utf8 字符串 unicode 代码点。
条件c
你必须能够遍历加密字符串 使用相同的笔画数 键盘上的向左或向右箭头键为 原始字符串 (给定如上所述的理想情况)。 这意味着两者 男人女人男孩女孩家庭表情符号 和梵文字符, 编码时,必须分别对应 恰好是另一个可打印字符,而不是一组 的“无意义”代码点 箭头键将解释为不同的字符。 这也意味着单个代码点字符可以 可能被转换为多码点字符 反之亦然。
条件d
与任何加密/解密算法一样, 要加密的字符串和 已解密的字符串 (最终结果)必须 包含完全相同的代码点 (两个字符串必须相等)。
# Python 3.6:
import string
# build-in library
print(string.printable)
print(type(string.printable))
print(len(string.printable))
# length of the string (number of ASCII characters)
#perl6
use v6;
my @ordinals = <128104 8205 128105 8205 128103 8205 128102>;
#array of the family codepoints
@ordinals.append(<307 13 2325 2381 2359 2367 32 65279 127137>);
#add the other codepoints
my $result_string = '';
for @ordinals {
$result_string = $result_string ~ $_.chr;
}
# get a string of characters from the ordinal numbers
say @ordinals; # the list of codepoints
say $result_string; # the string
say $result_string.chars; # the number of characters.
say $result_string.comb.perl; # a list of characters in the string
python 结果:
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'()*+,-./:;?@[]^_`{|}~
类'str'
100
perl6 结果:
[128104 8205 128105 8205 128103 8205 128102 307 13 2325 2381 2359 2367 32 65279 127137]
??????????????????????ij क्षि ????
8
("????????????????", "ij", "\r", "क्", "षि", " ", "", " ????").Seq
【问题讨论】:
-
嗯,我刚刚在 10 分钟前发布了这个问题,而且我已经有了 -2。我的问题有什么问题?
-
请注意,Unicode 字素簇的数量是无限的,因为簇可以包含任意数量的组合标记。所以你的密码可能应该基于单个代码点。
-
我的建议:编码unicode字符串,然后用BASE64编码。然后你有 64 个符号并在它们上使用凯撒。无论如何:这是一个弱加密。不用于实际情况。
-
文本的复杂性促使现代密码不处理字符。它们处理输入和输出的字节。如果输入是文本,则必须告知接收者字符编码。如果必须以文本形式进一步处理输出,则使用 Base64 或类似的。期望密码的输出看起来像文本通常不是目标。
-
@GiacomoCatenazzi 一般来说,组合字符的数量没有限制。 stream-safe text format 指定最多 30 个非初学者,但这种格式不是强制性的。
标签: python unicode raku caesar-cipher