Ari*_*fan 0 python unicode perl6 caesar-cipher
我想创建一个凯撒密码,它可以从整个Unicode(私有使用区域除外)编码/解码unicode可打印字符(单和多码点字形集群,表情符号等).优选地,它将使用所有可打印字符的列表.
注意:即使我想创建一个caesar密码,它实际上不是关于加密.问题是关于调查unicode的属性.
我发现了这些问题:
但我没有得到我想要的答案.
注意:如果您给出编码答案,我最感兴趣的是使用python3或perl6的解决方案,因为它们是我的主要语言.
最近,我被赋予编写凯撒密码的任务,然后对英文文本进行编码和解码.
我通过使用字符串库的内置string.printable常量在python中解决了它.这是常量的打印输出:(我使用了visual studio代码)
文档说:'''ASCII字符串,被认为是可打印的.这是数字,ascii_letters,标点符号和空格的组合.''' https://docs.python.org/3.6/library/string.html#string-constants
以下是我对可打印字符的含义的理解:
当我将python字符串常量保持在上面,并使用键盘上的左侧或方向箭头键遍历它时,我只需要100个笔画即可到达末尾(与字符数相同).看起来在作为可打印字符和可以通过箭头键的一个笔划进行遍历之间存在一对一的对应关系.
现在考虑这个字符串:
"ijक्षि"
基于pythons string.printable常量,这个字符串在我看来由以下7个可打印字符组成:(您可以在以下位置查找各个代码点:https://unicode-table.com/en/)
1(家庭)2(拉丁小Ligature Ij)3(cariage return)4(Devanagari kshi)5(空间)6(零宽度不间断空间)7(黑桃王牌)
代码点:128104 8205 128105 8205 128103 8205 128102(参考:https://emojipedia.org/family-man-woman-girl-boy/ )
(Latin Small Ligature Ij)ijcodepoint:307
(回车)代码点:13
(Devanagari kshi)क्षिcodepoints:2325 2381 2359 2367
(参见本页:http://unicode.org/reports/tr29/ )(代码点似乎是十六进制而不是数字)
(空格)码点:32
(零宽度不间断空间)代码点:65279(AKA U + FEFF BYTE ORDER MARK(BOM))(https://en.wikipedia.org/wiki/Byte_order_mark)
(黑桃牌扑克牌)代号:127137
当我将这个字符串粘贴到记事本中,并尝试用箭头键遍历它时,我最终使用了10个键击而不是7个键,因为家族表情符号需要4个键击(可能是因为记事本无法处理零宽度连接符,代码点:8205,当然记事本不能显示家庭标志符号).另一方面,当我将字符串发布到谷歌搜索时,我可以用7个笔画遍历整个字符串.
然后我尝试在Perl6中创建字符串以查看Perl6的字形意识对字符串的影响:
(我使用Atom编辑器)
perl6认为Devanagari kshi角色(4个代码点)实际上是2个字形,每个字形有2个代码点.即使它可以表示为两个字符,如上面的列表所示,我认为这是一个错误.Perl6应该是字形意识,甚至我的Windows记事本(和谷歌搜索)认为它是一个字素/字符.
基于2个字符串,可打印字符的实际定义似乎是这样的:'它是任何unicode代码点的组合,可以在理想的环境下通过键盘上的一个左或右箭头键来遍历.
"在理想环境下"意味着您正在使用的环境可以说就像谷歌搜索一样:也就是说,它可以识别例如表情符号(4人家族)或字形集群(梵文字符)作为一个可打印的字符.
3个问题:
1:以上是unicode中可打印字符意味着什么的公平定义?
2:无论你是否接受这个定义,你知道任何覆盖当前使用的unicode平面和可能的字形集群的可打印字符列表,而不仅仅是python字符串库所拥有的100个ASCII字符(如果我有这样的列表)我想我可以很容易地创建一个密码)?
3:鉴于这样的列表不存在,并且您接受该定义,您将如何创建这样一个列表,我可以创建一个凯撒密码,可以在给定以下4个条件的情况下加密任何/所有可打印字符?
注意:这4个条件正是我想象的适当的凯撒密码所需要的.
条件a
要加密的字符串将是一个有效的utf8字符串,包含标准的unicode代码点(没有未分配的或私有的区域代码点)
条件b
加密字符串也必须是由标准unicode代码点组成的有效utf8字符串.
条件c
您必须能够使用相同数量的笔划遍历加密的字符串,并使用键盘上的左或右箭头键作为原始字符串(给定如上所述的理想情况).这意味着男女 - 男孩 - 女孩家庭表情符号和梵文字符在编码时必须各自对应于一个其他可打印字符,而不是箭头键将被解释为不同字符的一组"非现实"代码点.它还意味着可以将单个代码点字符转换为多代码点字符,反之亦然.
条件d
与任何加密/解密算法一样,要加密的字符串和已解密的字符串(最终结果)必须包含完全相同的代码点(2个字符串必须相等).
# 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
Run Code Online (Sandbox Code Playgroud)
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"#$%&'()*+, - /:; <=> @ [] ^ _`!?{|}〜
class'str'
100
[128104 8205 128105 8205 128103 8205 128102 307 13 2325 2381 2359 2367 32 65279 127137]
ijक्षि
8
("","ij","\ r","क्","षि","","","").Seq
TL; DR我认为你的问题是合理的,应该得到比我迄今为止所写的更好的答案.我们来谈谈.
我认为任何人都不能根据您列出的要求创建一个Caesar密码,原因有多种.
但是,如果你的目标是"调查Unicode的属性"而不是创建一个密码,那么可能无关紧要.
当然,我可能只是经历了想象力的失败,或者只是在花费数年时间努力解决Unicode问题.
如果你通过评论批评下面我的解释的技术方面,我会尝试改进它,希望我们都会随时学习.TIA.
这是你标题中的干净配方.
唯一有问题的部分是"Caesar","cipher","all","Unicode","printable"和"characters".我们一起去吧.
凯撒密码是一种特别简单的单字母密码.Unicode不是一个大的单个大字母表.但也许您可以将其代码点的子集视为它们.
我会说这就是具有所有unicode角色的SO Cipher的全部内容.
你现在已经拒绝了这一点,并引入了一系列额外的方面,这些方面要么不可能,要么难以实现.
忽略调查Unicode属性的优先级,如果您选择使用常规ASCII密码,则会有意义.或者也许回到那个密码所有的unicode角色,然后回到他们离开的地方,也许会注意到,根据对SO的评论,他们显然只停留在BMP飞机上:
请注意,您只使用BMP代码点(即从U + 0000到U + FFFF).Unicode范围从U + 0000到U + 10FFFF,因此您缺少大约一百万个代码点:)
所以也许你可以做得更好.我不认为从创建密码本身的角度来看是值得的,但它可能是为了更多地了解Unicode的属性.
@TomBlodget在对你的问题的评论中指出:
文本的复杂性促使现代密码不处理角色.它们处理输入和输出的字节.在输入是文本的情况下,必须告知接收者字符编码.如果输出的进一步处理必须是文本,则使用Base64或类似的.期望密码的输出看起来像文本通常不是目标.
如果您需要Unicode密码的通用解决方案,请遵循Tom的配方.
关于你关于字素数量的问题的评论@nwellnhof注意到:
有一个无限的数字
但是你还合理地回答说,在任何给定的文本中只会有一个有限的数字; Unicode的意图是,如果给出简并输入,那么符合Unicode的软件可能/将产生mojibake结果(其中计算为简并在Unicode更新中稍微开放一些); 而那就是你希望继续前进的基础.
这是一个合理的回应,但即使被限制为"所有非退化"和"只能出现在现实生活中的那些",你仍然不能拥有"全部",因为仍然有一个有效的无限数量的良好形成和潜在合理字符.
我应该在这里插入一些计算来解决这个问题."有效无限"是万亿吗?为什么?诸如此类的事情.但在深入研究之前,我将等待评论.
让我们假装它是一万亿,这不是问题,继续前进.
Unicode非常复杂.
你已经获得了生产凯撒密码的任务,这是一件非常简单的事情.
他们真的不能很好地混合,除非你非常注重保持简单.
但是您想要研究Unicode的属性.所以也许你想要涉足所有的复杂性.但问题是,你想花几年时间探索打开这个潘多拉盒子的后果?(我已经研究和开发了十年的Unicode.它很复杂.)
您链接到SO问题"Unicode可打印字符的范围是什么?".这包括一个答案:
你对Unicode的了解越多,你就越能意识到人类书写系统出乎意料的多样化和不可思议的奇怪.特别是特定的"字符"是否可打印并不总是显而易见的.
但是你可能会读到这一点而拒绝被吓倒.这既令人钦佩又惹麻烦.例如,它似乎驱使你将"可打印"定义为"需要一个或多个击键来遍历"这样的事情是如此充满,以至于很难知道从哪里开始 - 所以我会在此之后直到回答.
鉴于你的目标是编写一个凯撒密码,这是几千年前用于角色的密码,因此你专注于"用户认为是一个角色"是有意义的.
根据Unicode的定义,这被称为"字形".
你的一个示例字符清楚地表明了"用户认为什么是字符"(字母)和代码点(Python认为是一个字符)之间的区别是多么有问题:
print('????'[::-1])
????
Run Code Online (Sandbox Code Playgroud)
这显示了用梵文写成的单个"字符"(单个字素)的修剪,根据维基百科,"世界上最常用和采用的书写系统之一".
(或者,如果我们想忽略这个星球的一半,那么这种破坏会更常见地影响并且只关注那些认为安全的人:
print(''[::-1])
Run Code Online (Sandbox Code Playgroud)
这是一个国家变成另一个国家的旗帜.幸运的是,标志很少出现在文本中 - 尽管现在正在改变文本是越来越随意的Unicode文本,就像我正在写的文本一样 - 并且标志字符并不那么重要,英国和保加利亚都是欧盟的成员所以它可能不是和十亿印度人的文字一样糟糕.)
所以你很合理地想到自己,"也许Perl 6会有所帮助".
引用UAX#29,关于"Unicode文本分段"的Unicode附件文档:
本文档定义了字形集群的默认规范.
Perl 6实现了字形集群机制.它原则上可以以各种方式聚类,但是现在它实现了默认规范.这就是允许Perl 6避免Python在上面犯的错误的原因.
但Unicode文档仍在继续:
[字形集群的规范]可以针对特定语言,操作或其他情况进行定制.
所以你不能只是看一些文本(或者给它一些软件)并说出它包含什么"字符",如果用"字符"表示"用户认为是一个字符".
情况变得更糟......
"ijक्षि"...记事本... 10个关键的笔触...谷歌搜索... 7笔... Perl6 ... Atom编辑器... perl6认为क्षि...实际上是2个字素......我认为这是一个错误...记事本(和谷歌搜索)认为它是一个字素/字符
对我来说,谷歌搜索需要10次击键 - 因为它与谷歌搜索无关,而是与我的系统方面有关,包括我正在使用的网络浏览器(Firefox)和其他细节.
有些编辑器可以配置,因此根据你配置它们的方式和/或你指定的文本写入的语言,对'षष'(或'fi')的过程可以是1或2次击键.对我来说,编辑这个SO在Linux Mint上使用Firefox回答,它需要2次击键才能将光标移到上.
.chars默认情况下,Perl 6正确地将'क्षि' 的结果报告为2,因为根据默认的字形表聚类规范,这就是Unicode所说的.("Extended Grapheme Clusters".)这恰好与Linux Mint上的Firefox编辑这个SO答案的情况相匹配,因为星星排队并且是星期天.
记事本或其他软件合理地只需要一次按键就可以将光标移到其他位置,而其他编辑则合理地选择两种,因为根据Unicode规范这两种情况都是合理的:
箭头键移动... 可以使用特定字体特有的知识以更细化的方式移动,在编辑单个组件有用的情况下
我强调了.Unicode将其留给软件来决定光标的移动方式.
1:以上是unicode中可打印字符意味着什么的公平定义?
我不这么认为.希望前面的内容解释了为什么,或者至少指出了你需要研究(一年或三年)的方向来理解原因.
2:...你知道任何覆盖当前使用的unicode平面和可能的字形集群的可打印字符列表......
有如此多的"可能的字形集群"可以合理地发生,即使排除退化的代码点组合,也会留下有效的无限列表.
任何人可能创建的任何小子集都不会是规范的,因为Unicode联盟不会祝福它,民众会争论应该包括什么.
3:...你将如何创建这样一个列表,我可以创建一个caesar密码,可以在给出以下4个条件的情况下加密任何/所有可打印字符?
首先,你的条件太费劲了.请参阅下一节.
但是,即使你放弃了那些太难的东西,它仍然太难了,结果太无趣了,无法做任何有价值的事情.
4:如果您认为创建这样的列表是一个糟糕的想法,您将如何创建密码?
如果它是我,它必须是一个凯撒密码,我会让它只是处理字节,根据汤姆在这个答案开头的评论.
要加密的字符串将是一个有效的utf8字符串,包含标准的unicode代码点(没有未分配的或私有的区域代码点)
它需要比这更受限制,但有理由说它需要是一个有效的Unicode字符串.如果你想坚持认为它也很好.
加密字符串也必须是由标准unicode代码点组成的有效utf8字符串
当然.
您必须能够使用与原始字符串相同的笔划数来遍历加密的字符串
你可以为一小部分Unicode字符使用它.但...
这意味着[天蝎座角色的原始和编码版本的一次击键] [क्षि]
......不是一个合理的要求.
如果为密码编写了字形集群的自定义实现,则可以确保给定文本的字形集群(字符)解释相同,这是用于控制光标的字形集群实现的忠实副本.
但是,然后你必须保持这两个代码库以保持它们同步.这只适用于一种特定的系统配置.
这将是一个荒谬的痛苦.对于零,或者至多是微小的增益.
要加密的字符串和已解密的字符串(最终结果)必须包含完全相同的代码点(2个字符串必须相等).
所以,没有规范化.
这排除了所有Perl 6的字形意识好处.
然后,无论如何,你需要关注字素,因为它们实际上是无数的.
我的回答只涉及它涵盖的主题,可能包含很多错误.如果你批评它我会尝试改进它.