Algorithm 用字母表编码字节数组,输出看起来应该是随机分布的
我正在编码二进制数据Algorithm 用字母表编码字节数组,输出看起来应该是随机分布的,algorithm,random,encoding,base64,Algorithm,Random,Encoding,Base64,我正在编码二进制数据b1,b2。。。bn使用字母表。但是由于bs的二进制表示或多或少是顺序的,因此位到字符的简单映射会产生非常相似的字符串。例如: encode(b1) => "QXpB4IBsu0" encode(b2) => "QXpB36Bsu0" ... 我正在寻找使输出更“随机”的方法,这意味着在查看输出字符串时更难猜测输入b 一些要求: 对于不同的bs,输出字符串必须不同。对相同的b进行多次编码不一定会产生相同的输出。只要不同输入bs的输出字符串之间没有冲突,一切正常
b1,b2。。。bn
使用字母表。但是由于b
s的二进制表示或多或少是顺序的,因此位到字符的简单映射会产生非常相似的字符串。例如:
encode(b1) => "QXpB4IBsu0"
encode(b2) => "QXpB36Bsu0"
...
我正在寻找使输出更“随机”的方法,这意味着在查看输出字符串时更难猜测输入b
一些要求:
- 对于不同的
s,输出字符串必须不同。对相同的b
进行多次编码不一定会产生相同的输出。只要不同输入b
s的输出字符串之间没有冲突,一切正常b
- 如果它很重要:每个
大约为50-60位。字母表包含64个字符b
- 编码函数不应产生比您仅使用从
s位到字母表字符的简单映射得到的输出字符串更大的输出字符串(给定上述值,这意味着每个b
约10个字符)。因此,仅仅使用像SHA这样的散列函数是不可取的b
xxxx
r
以获得rrxxxx
val char=alphabet[rrxxxx]
并将其添加到结果中(因为字母表的大小是64)rrrxxx
甚至rrrrxx
),但输出会越来越大。我上面提到的一个要求是不增加输出字符串的大小。目前我只使用这种方法,因为我没有更好的想法
作为一种替代方法,我考虑在应用字母表之前对输入的b
位进行洗牌。但是,因为必须保证不同的b
s会产生不同的字符串,所以洗牌函数应该使用某种确定性(可能是一个秘密数作为参数),而不是完全随机的。我没能想出这样一个函数
我想知道是否有更好的方法,任何提示都值得赞赏。基本上,您需要从每个可能的50位值到另一个50位值的可逆伪随机映射。您可以使用可逆(用于某些伪随机数生成器的那种)来实现这一点 编码时,在前进方向将LCG应用于您的号码,然后使用base64编码。如果需要解码,请从base64解码,然后在相反方向应用LCG以恢复原始号码
包含可逆LCG的一些代码。你需要一个周期为250的。用于定义LCG的常数将是您的密码。基本上,您需要从每个可能的50位值到另一个50位值的可逆伪随机映射。您可以使用可逆(用于某些伪随机数生成器的那种)来实现这一点 编码时,在前进方向将LCG应用于您的号码,然后使用base64编码。如果需要解码,请从base64解码,然后在相反方向应用LCG以恢复原始号码 包含可逆LCG的一些代码。你需要一个周期为250的。用于定义LCG的常量将是您的密码。您想使用密码。这将获取序列键并将其转换为非序列号。键与其结果之间存在一对一的关系。因此,没有两个数字会创建相同的非顺序密钥,并且该过程是可逆的 我有一个用C#编写的小例子,说明了这个过程
private void DoIt()
{
const long m = 101;
const long x = 387420489; // must be coprime to m
var multInv = MultiplicativeInverse(x, m);
var nums = new HashSet<long>();
for (long i = 0; i < 100; ++i)
{
var encoded = i*x%m;
var decoded = encoded*multInv%m;
Console.WriteLine("{0} => {1} => {2}", i, encoded, decoded);
if (!nums.Add(encoded))
{
Console.WriteLine("Duplicate");
}
}
}
private long MultiplicativeInverse(long x, long modulus)
{
return ExtendedEuclideanDivision(x, modulus).Item1%modulus;
}
private static Tuple<long, long> ExtendedEuclideanDivision(long a, long b)
{
if (a < 0)
{
var result = ExtendedEuclideanDivision(-a, b);
return Tuple.Create(-result.Item1, result.Item2);
}
if (b < 0)
{
var result = ExtendedEuclideanDivision(a, -b);
return Tuple.Create(result.Item1, -result.Item2);
}
if (b == 0)
{
return Tuple.Create(1L, 0L);
}
var q = a/b;
var r = a%b;
var rslt = ExtendedEuclideanDivision(b, r);
var s = rslt.Item1;
var t = rslt.Item2;
return Tuple.Create(t, s - q*t);
}
private void DoIt()
{
常数长m=101;
const long x=387420489;//必须是m的互质
var multInv=乘法逆(x,m);
var nums=new HashSet();
用于(长i=0;i<100;++i)
{
var编码=i*x%m;
已解码变量=已编码*多NV%m;
WriteLine(“{0}=>{1}=>{2}”,i,编码,解码);
如果(!nums.Add(编码))
{
控制台。写入线(“副本”);
}
}
}
专用长乘法反转(长x,长模)
{
返回扩展的欧几里德视觉(x,模数)。项1%模数;
}
私有静态元组扩展欧几里德视觉(长a,长b)
{
if(a<0)
{
var结果=扩展欧几里德视觉(-a,b);
返回Tuple.Create(-result.Item1,result.Item2);
}
if(b<0)
{
var结果=扩展欧几里德视觉(a,-b);
返回Tuple.Create(result.Item1,-result.Item2);
}
如果(b==0)
{
返回元组。创建(1L,0L);
}
var q=a/b;
var r=a%b;
var rslt=扩展的欧几里德视觉(b,r);
var s=rslt.Item1;
var t=rslt.Item2;
返回Tuple.Create(t,s-q*t);
}
上述文章中的代码抄袭,以及支持材料
这样做的想法是,取你的序列号,计算逆数,然后用base-64编码。要反转此过程,请对给定的值进行base-64解码,然后进行反向计算,得到原始数字。如果要使用。这将获取序列键并将其转换为非序列号。这是一对一