如何用Jasypt进行安全加密?

在jasypt.org上,关于 "我可以解密一个加密的密码吗?"的问题,它在这里说 Jasypt: Java simplified encryption - Frequently Asked Questions :“如果你用消息摘要技术加密了它,这正是你应该做的(通过使用PasswordEncryptor实现,StandardStringDigester或类似的…),你不能。

我必须说我已经尝试了各种方法,但在我看来,我总是遇到同样的问题。我不知道为什么Jasypt要让每个人都能解密到原始值。例如,我可以很容易地加密它,但也可以用mvn命令解密它。

用Jasypt加密和解密的例子。

encrypt:

mvn jasypt:encrypt-value -Djasypt.plugin.value="test" -Djasypt.encryptor.password="pass" -Djasypt.encryptor.algorithm="PBEWithMD5AndDES" -Djasypt.encryptor.key-obtention-iterations=1000 -Djasypt.encryptor.pool-size=1 -Djasypt.encryptor.provider-name="SunJCE" -Djasypt.encryptor.salt-generator-classname="org.jasypt.salt.RandomSaltGenerator" -Djasypt.encryptor.iv-generator-classname="org.jasypt.iv.NoIvGenerator" -Djasypt.encryptor.string-output-type="base64"

正如你所看到的,在第一条命令中,我提供了值 "test"和密码 "pass"来进行解密。它生成了。ENC( u7uKa3B9Xfey+zZ46tOmag== )

这样,我就可以很容易地执行第二条命令,我将得到原始值,即 “test”。

decrypt:

mvn jasypt:decrypt-value -Djasypt.plugin.value="u7uKa3B9Xfey+zZ46tOmag==" -Djasypt.encryptor.password="pass" -Djasypt.encryptor.algorithm="PBEWithMD5AndDES" -Djasypt.encryptor.key-obtention-iterations=1000 -Djasypt.encryptor.pool-size=1 -Djasypt.encryptor.provider-name="SunJCE" -Djasypt.encryptor.salt-generator-classname="org.jasypt.salt.RandomSaltGenerator" -Djasypt.encryptor.iv-generator-classname="org.jasypt.iv.NoIvGenerator" -Djasypt.encryptor.string-output-type="base64"

在我的.pom文件中,我在依赖关系部分定义了这个。

<dependency>
    <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot</artifactId>
    <version>3.0.2</version>
</dependency>

在构建部分也是如此(所以我可以通过maven执行jasypt)。

<plugins>
    <plugin>
      <groupId>com.github.ulisesbocchio</groupId>
      <artifactId>jasypt-maven-plugin</artifactId>
      <version>3.0.2</version>
    </plugin>
<plugins>

我的应用程序yml看起来像这样。

jasypt:
    encryptor:
        password: pass
        algorithm: PBEWithMD5AndDES
        key-obtention-iterations: 1000
        pool-size: 1
        provider-name: SunJCE
        salt-generator-className: org.jasypt.salt.RandomSaltGenerator
        iv-generator-className: org.jasypt.iv.NoIvGenerator
        string-output-type: base64
        
spring:
  datasource:
    database-name: *****
    jdbc-url: *****
    username: *****
    password: ENC(u7uKa3B9Xfey+zZ46tOmag==)

一切都很正常(我也试过通过java代码的bean,它完全一样,只是风格不同)。但是,我为什么要这样做,并让它这样下去,因为我知道黑客可以像我一样,执行这个命令并获得实际的价值。

他可以做到这一点,而且他拥有他所需要的一切–他可以从我的代码中读取 " u7uKa3B9Xfey+zZ46tOmag== " 和 " pass ":解密。

mvn jasypt:decrypt-value -Djasypt.plugin.value="u7uKa3B9Xfey+zZ46tOmag==" -Djasypt.encryptor.password="pass" -Djasypt.encryptor.algorithm="PBEWithMD5AndDES" -Djasypt.encryptor.key-obtention-iterations=1000 -Djasypt.encryptor.pool-size=1 -Djasypt.encryptor.provider-name="SunJCE" -Djasypt.encryptor.salt-generator-classname="org.jasypt.salt.RandomSaltGenerator" -Djasypt.encryptor.iv-generator-classname="org.jasypt.iv.NoIvGenerator" -Djasypt.encryptor.string-output-type="base64"

他只需要从yml文件中读取这个ENC( u7uKa3B9Xfey+zZ46tOmag==)(他可以这样做,而 "pass"也来自yml文件(他也可以这样做)。就这样,他可以拿回原始值。我看不出这有什么安全性。黑客只需要知道如何执行mvn解密命令(在这个例子中我已经成功做到了,为什么有人不能做到呢),而且这基本上和加密是一样的。

有人可能会说,‘好吧,你可以通过环境变量传递你的密码(“pass”)’。这对我来说是行不通的。因为Gitlab和Dockerfile的文件,我都在项目中,如果我在那里设置了这些变量,黑客仍然可以读取它,并在几秒钟内得到实际值。它们是与我的项目绑定的。另外,在Gitlab或Kubernetes这样的系统上提供实际的密码作为环境变量,在我看来是非常危险的。黑客,如果他是非常高级的,也可以读取这些值。所以为什么要把它们暴露出来。而这似乎是Jasypt的唯一解决方案,即设置APP_ENCRYPTION_PASSWORD这样的变量。

我的问题是,你能不能以某种方式禁用Jasypt的解密功能,以便不得到实际的值,这样黑客就不能得到它了?对我来说,这似乎是最安全的选择。或者一些类似的解决方案来解决我的问题?如果可以的话,请提供一个例子。**如果Jasypt能以某种方式在飞行中生成密码就好了,就像它生成盐一样,但是怎么做呢。我知道,那么人应该动态地填充yml文件,这是不可能的。如果我只需要密码和加密值来解密原始值,我真的看不出用Jasypt是如何安全的。在我看来,黑客可以读取源代码,这似乎是非常糟糕的安全。然后,在yml文件中屏蔽数据库密码的目的是什么。如果一切都可以在几秒钟内被解开。这在我看来是非常薄弱的安全。请告诉我怎样才能使它比现在的方式更安全。


StackOverflow:java - How to make safe encryption with Jasypt? - Stack Overflow