给你一个非常简单和坏的例子。数据分为4位。 16个可能的数字对应于前16个辅音。您添加随机元音以使其可发音。所以“08F734F7”可以成为“ba lo ta ku fo go ta ka”。你可以加入一些音节并添加标点符号和大写字母,它可以成为“Balo ta kufogo,Taka?”看起来像是一种看似合理的语言。
为了说清楚,我不是想保护二进制数据。
我想在压缩和加密我的(UTF-8)纯文本日记后使用它。生成的二进制数据看起来应该是随机的。我需要将这些数据转换为看似合理的语言,并能够将其还原。我要在纸上打印“语言”并制作一本自定义书籍。
所以我正在寻找的是将随机数据转换成可读的合理单词的最佳方法。好的,我的意思是最大的字母比例(同时使它看起来像一个真正的语言)。在我的例子中,每个字母正好是2位。或者一个字节的4个字母。
答案 0 :(得分:3)
FASCINATING问题!
到目前为止,我的最佳解决方案是以2到4个字符对12位进行编码,每个字母给出3到6位。 (星期五不是对字长不均匀分布进行必要数学处理的好日子,所以我没有算出每个字母的平均位数。)
这个想法是使用以一个或两个辅音开头的“音素”,并以一个或两个元音结尾。有21个辅音,我觉得每个辅音都可以跟着h,l,r,w或y,但看起来仍然合理。所以你的音素从126个辅音部分中的一个开始--b,bh,bl,br,bw,by,c,ch,cl,cr,...,z,zh,zl,zr,zw,zy(诚然,认为像yy和zl看起来有点奇怪,但它毕竟是外语:))
126非常接近128,我们可以为最后两个值添加t'和b'(例如) - 为我们提供128个值的字典,以存储7位。您甚至可以使用p'或其他任何内容将d'和zl替换为yy。
类似地,元音部分可以是单个元音或一对元音。我已经删除了aa,ii和uu,因为它们看起来对我来说太奇怪了(个人偏好),即使它们确实出现在一些真实的单词中(决定“连续统一体”应该拼写那样!)。所以这给出了27个可能的元音部分:a,e,i,o,u,ae,ai,ao,...,ue,ui,uo。27接近32,所以使用重音元音(é,â等)输入5个值。这给了我们5位,带来了一些稀疏重音的额外好处。
这是2位,3位或4位字母的12位。
为了更有趣,如果下一位为1,则90%的时间(随机)插入空格,或者标点符号另外10% - 但如果下一位是0,则不要插入什么 - 只需开始下一个音素。将标点符号后的第一个字母大写。
那应该给你一些:
Bwaijou t'ei plo ku bhaproti! Llanoiproimlaroojaévli。
也许有人可以接受它。
答案 1 :(得分:2)
答案 2 :(得分:0)
我个人会使用c ++。对于一个可以做你所描述的程序,我会做这样的事情:
void JumbleData(const void *src, int srcLen, char *dest)
{
for(int i = 0; i < srcLen; i++)
{
unsigned char data = *((unsigned char*)src+i);
unsigned char lower = data & 0x0F;
unsigned char higher = (data & 0xF0) >> 4;
dest = 'a' + lower; dest++;
dest = 'a' + higher; dest++
}
}
这应该将src数据分成4个部分,将其添加到'a'并将其放在目标中。然后你可以通过并在它们之间添加额外的字母,但只要你有一个字符串方式来反转过程。
为了使它不那么明显我一次使用超过4位,但也不是偶数8位。以下是使用6位块的示例:
void AddData(char* &dest, unsigned char data);
void JumbleData(const void *src, int srcLen, char *dest)
{
for(int i = 0; i < srcLen; i+=3)
{
unsigned char data0 = *((unsigned char*)src+i);
unsigned char data1 = *((unsigned char*)src+i+1);
unsigned char data2 = *((unsigned char*)src+i+2);
unsigned char chunk0 = data0 & 0x3F;
unsigned char chunk1 = (data0 >> 6) | ((data1 & 0x0F) << 2);
unsigned char chunk2 = (data1 >> 4) | ((data2 & 0x03) << 4);
unsigned char chunk3 = data2 >> 2;
AddData(dest, chunk0);
AddData(dest, chunk1);
AddData(dest, chunk2);
AddData(dest, chunk3);
}
}
void AddData(char* &dest, unsigned char data)
{
const char vowels[] = {'a', 'e', 'i', 'o'};
char letter1 = 'a' + (data & 0x0F);
char letter2 = vowels[((data & 0x0C) >> 2)];
char letter3 = 'n' + ((data & 0x3C) >> 2);
*dest = letter1;
dest++;
*dest = letter2;
dest++;
*dest = letter3;
dest++;
*dest = ' ';
dest++;
}
对于每个6位的块,这会产生3个字母的混乱。
答案 3 :(得分:0)
您可以使用设置转换表执行简单的替换算法,该表根据原始数字中数字的功率而变化。对转换表中的值进行加权,以便元音和某些辅音更常见。选择一些足够大的基地,以便在各个地方各种各样。例如。 (基于十六进制的数据):
value | place
| 0 1 2 ...
------|------ - - -
0 | a a a ...
1 | e e e
2 | i i i
3 | o o q
4 | u u w
5 | y q r
6 | q w f
7 | w r g
8 | r f h
9 | t g j
A | p h k
B | s j c
C | d k v
D | f l b
E | g z n
F | h x m ...
(这也可以通过每列简单精心选择的公式来完成......)
所以,
B4B => "suc"
3AA => "ohk"
F62 => "iwm"
...
将其扩展到足够的列以便很好地控制所有字符的分布。如果您的源数据没有完全随机的分布,您可能还想将列中的顺序混合在一起。注意每列中是否存在某些字符,有些字符只存在一次。还可以通过改变每列中的平均比率来调整辅音频率的元音。
获取大量固定大小的数据块并通过转换器运行它们,然后应用间距/标点符号/大小写算法。
(无法保证你不会得到所有辅音或极低元音数字,但你可以使用大写算法使其全部大写看起来像一个首字母缩略词/初始主义)
答案 4 :(得分:0)
这是一个老问题,但非常有趣。
一旦我想做类似的转换,但有其他目标。 Guid(uuids)通常不会对眼睛友好,因此我不得不将其转换为合理的单词。最后的系统是基于前两个之后英文字母的出现。该表是使用英语句子语料库制作的,并且排除了很少使用的语句。 所以决赛桌包含看起来像
的线条 ...
(key:'_t'; next:'aehioruwy'),
(key:'_u'; next:'lmnprst'),
(key:'_w'; next:'aehiory'),
(key:'ab'; next:'abeilorsuwy'),
(key:'ac'; next:'_acehikloqrtuy'),
...
包含大约200-300行,其中'next'是可以出现在'key'字母后面的所有可能字母(_是单词的开头或结尾,取决于它是在键中还是在下一行中)。
转换过程取当前值,除以模数长度(下一个)并将余数作为相应的字母作为下一个“似是而非”的符号,商变为新的当前值。为了避免长字,有一种技巧可以明确地结束通过编码和解码对称使用的字。该系统可以产生例如这样的序列(每个序列的输入是128位guid / uuid)
Furepas_Wann_Hunkare_Rylacid_Makinuag_Dreem
Togo_Ragam_Omb_Bonsbe_Gonn_Eclecki_Op
或者我们采用一些广泛使用的指南,例如MS IWebBrowser2 {D30C1661-CDAF-11D0-8A3E-00C04FC9E26E}
Lakar_Rupplex_Waylagit_Munghim_Paddato_Molu
(“Lakar Rupplex”是一个很好的浏览器人名,不是吗?)
对于密度,该系统每字母密度约为3位。
答案 5 :(得分:-3)
请阅读http://email.about.com/cs/standards/a/base64_encoding.htm
Base64编码占用三个字节, 每个由8位组成,和 将它们表示为四个可打印的 ASCII标准中的字符。它 这基本上是两个步骤。
第一步是转换三个 字节到四位数的六位。 ASCII标准中的每个字符 由七位组成。仅限Base64 使用6位(对应于2 ^ 6 = 64 字符)以确保编码数据 可打印和人性化的可读性。没有 可用的特殊字符 使用ASCII。 64个字符 (因此名称Base64)是10位数, 26个小写字符,26个大写字母 字符以及'+'和'/'。
例如,如果三个字节是 155,162和233,对应 (和可怕的)比特流是 100110111010001011101001,其中 turn对应于6位值 38,58,11和41。