2

我开始学习 javascript 中的函数式编程。这可能是一个愚蠢的问题,但我试图解决以函数方式编写的非纯函数。

我的问题是在函数式编程范式中应该使用什么策略来实现这一点。

const crypto = require('crypto');

const encrypt = (data, publicKey) => {
    if (publicKey === undefined ) throw 'Missing public key.';

    const bufferToEncrypt = Buffer.from(data);
    const encrypted = crypto.publicEncrypt({
        key: publicKey
    }, bufferToEncrypt);

    return encrypted;

};
4

1 回答 1

4

成为纯函数有两个标准。

纯函数准则 1:调用具有相同值的函数必须始终产生相同的返回值

这在进行非对称加密时是不可能的,因为每次操作都会生成一个随机会话密钥。会话密钥用公钥加密,然后会话密钥用于加密负载。返回的值通常只是两个值的编码版本:(1) 公钥加密的会话密钥,以及 (2) 会话密钥加密的有效负载。

每次调用该函数时,这两个值都会不同,因为会话密钥每次都会不同。

然而,尽管返回值比较不相等,但我认为它们在语义上是相等的——也就是说,如果你用匹配的私钥解密每个值,解密后的值将比较相等。

加密有效地混淆了值相等,对于加密来说这是一件好事。 我们不希望在没有解密密钥的情况下比较在不同时间生成的两条加密消息。那将是一个安全风险。

因此,我认为这个函数在语义上符合这个标准,但如果没有公钥,我们就无法判断。

纯函数准则 2:函数没有可观察到的副作用

这一点应该很明显:写入磁盘是副作用,写入全局变量是副作用等。我们应该无法区分调用函数前后的状态差异。

从技术上讲,会话密钥的生成将需要使用系统的安全随机数生成器。这将消耗一些熵。运行函数后,可用的熵会减少,这可以测量。

但是,我认为可以忽略这种副作用,因为任何需要安全随机数的东西都会有同样的问题,这更多是安全随机数生成器的实现细节

这就像声称需要大量 CPU 时间的函数具有副作用,因为运行它会增加进程的 CPU 时间计数器。是副作用吗?技术上……也许吧?但没有一个理性的人会认为这是副作用。

结论

我会称这个函数为“语义纯”。如果你问我这是否是一个纯函数,并且只接受没有条件的是/否答案,我会告诉你“是”。

于 2019-09-04T00:18:26.400 回答