字符串上的反摘要操作总是返回相同的值

Anti-Digest operation on string always returning the same value

本文关键字:返回 操作 字符串      更新时间:2023-10-16

我正在寻找某种方法来"摘要"字符串,但总是返回相同的32(或64)字节长的值(作为十六进制字符串或纯字符)。类似以下代码的操作:

std::string digest(const std::string& input)
{
    std::string result = "";
    // do something with the input string, update result accordingly
    return result;
}

还有更多的细节:我想要与经典摘要函数完全相反的功能,即对于每个不同的字符串,它返回一个不同但总是相同的(1比1)值。我想要一个函数,它为每个字符串每次返回相同的值(n到1)。

显然,每次返回相同常量result的"简单"解决方案不被视为解决方案:)代码实际上应该消化输入字符串,并作为操作的结果构建result

举个例子:

 digest ("fox") == digest ("whale")

应该是真的。

或者从数学上讲:

对于∀a和b如果a!=b=>摘要(a)==摘要(b)。这就是为什么我称之为反消化。

一个长的数学演示

您的要求是:

a!=b  =>   digest(a)==digest(b)

让我们取另一条消息——任何其他消息c,并假设它与a和b不同:

a!=c  =>  digest(a)==digest(c)  
b!=c  =>  digest(b)==digest(c) 

从中可以看出,对于任何c,摘要都是恒定的,除非它等于a或b。

现在拿另一条消息x不管它可能是什么:

c!=x  => digest(c)==digest(x)

通过对抗这个含义,这相当于:

digest(x)!=digest(c) => c==x

因此,假设有一个x,它的摘要不同于常量摘要(c)。我们有:

digest(x)!=digest(c) and digest(x)!=digest(a)
=>  x==c  and x==a 
=>  c==a  
=>  digest(c)!=digest(a)

但这与关于a,c,digest(a)和digest(c)的原始假设相矛盾,所以不可能有这样的x。所以你可以得出结论,你的digest必须是一个严格恒定的函数

现在假设你的函数不是恒定的:

digest(x)!=digest(a) =>  x==a  

但如果digest是一个函数,那么它将始终为相同的输入返回相同的结果,这意味着x==a=>digest(x)==digest(a)。这表明,除了常数函数之外,没有其他解决方案。

简而言之,在C++中

函数将为相同的参数返回相同的结果,除非有副作用(静态变量或其他什么)。在只有一个参数的函数中,您要求对不同的值具有相同的结果,但对相同的值具有不同的结果是不可行的。

我似乎不清楚自己想要实现什么。。。

无论如何,我想出了以下方法:

static const size_t DIGEST_SIZE = 32;
std::string antiDigest(const std::string& a)
{
    if(a.empty()) { throw "cannot digest empty string"; }
    char r[DIGEST_SIZE ] = {0};
    int block_size = std::min(DIGEST_SIZE, a.length());
    int block_count = 1 + DIGEST_SIZE / a.length();
    for(int i=0; i<block_size; i++)
    {
        int hlp = 0, bc = 0;
        while(bc < block_count)
        {
            int idx = i + bc * block_size;
            if(idx >= a.length()) break;
            hlp += a[idx];
            bc ++;
        }
        hlp = (int)(hlp << 3) + hlp;
        unsigned int hlp2 = 0;
        while(hlp)
        {
            int t = hlp - ((hlp/10) * 10);
            hlp2 += t;
            hlp /= 10;
        }
        bc = 0;
        while(bc < block_count)
        {
            int idx = i + bc * block_size;
            if(idx >= DIGEST_SIZE) break;
            r[idx] = ( (hlp2 / 10) + (hlp2-(hlp2/10)*10)) ;    
            bc++;
        }
    }
    std::stringstream result; 
    for(int i=0; i<DIGEST_SIZE; i++)
    {
        result << int_to_hex(r[i]) ;
    }
    return result.str();
}

在ideone上:http://ideone.com/t4dibL

显然,用逐位运算代替数学运算会使这一点更加模糊,但为了验证概念,这一点确实有效