java - secret 是否可以隐藏在提供访问凭据的 'safe' java 类中?

标签 java class security copy-protection

这是一个关于 Java 中可能(或不可能)的头脑 Storm 问题。我想知道是否可以在类中隐藏 secret 并阻止任何人仅使用 Java 代码或其任何功能访问它(安全性、反射、序列化、类加载器、您能想到的......)。

到目前为止,这是我的想法:

public final class Safe {
    
    private String secret;
    private HashMap<String, Credentials> validCertificates
            = new HashMap<String, Credentials>();
    
    public Safe(String aSecret) {
        this.secret = aSecret;
    }
    
    public final class Credentials {
        private String user;
        private Credentials(String user) {
            this.user = user;
        }
    }
    
    public final Credentials getCredential(String user) {
        // Following test is just for illustrating the intention...
        if ( "accepted".equals(user) ) {
            return new Credentials(user);
        } else {
            return null;
        }
    }
    
    public String gimmeTheSecret(Credentials cred) {
        if ( this.validCertificates.get(cred.user) == cred ) {
            return secret;
        } else {
            return null;
        }
    }
    
    private void writeObject(ObjectOutputStream stream) throws IOException {
        throw new RuntimeException("No no no no no no no!!!");
    }
    
}

可以改进吗?是否应该改进?将 secret 锁定在安全类中的想法不可能实现吗?

编辑

相关性:

有些人质疑我在这里提出的问题的相关性。虽然我问一个一般性问题是为了引发公开对话,但此类有一个非常具体的应用:

  • 如果我想解密一些消息,我需要将私钥数据加载到类中。如果我不能阻止其他 Java 代码访问它,那么就不可能创建一个安全的系统。当然,如果我想解密一条消息,我宁愿在类里面进行,也不愿泄露 secret ,但是,保险箱必须保持牢不可破。

澄清:

  • 类的实例仅在运行时创建,而不是在编译时创建
  • 代码可以在网络服务器应用程序或任何桌面或设备应用程序中运行
  • 该类仅用于在运行时在内存中存储 secret ,不打算持久化它(为了持久化,可以/应该使用经典的加密技术)

事实:

  • 要在 Java 应用程序中实现安全性,应设置一个 SecurityManager 实例,其中根据需要重写检查方法
  • 此应用程序可以使用安全类加载器加载不受信任的代码,并为其加载的类分配保护域。此域不应包含 RuntimePermission("setSecurityManager")。
  • 不受信任的代码可以尝试更改 SecurityManager,但由于安全类加载器未授予 setSecurityManager 权限,因此将引发 SecurityException。

已解决的问题:

关于执行环境,我们需要区分两种情况:

  • 受控环境:我们启动的应用程序将使用不受信任的代码来尝试破坏我们的“安全”。

如果我们设置适当的 SecurityManager,禁用反射并限制任何加载的不受信任代码的权限,那么我们的 secret 就是安全的。

  • 不受控制的环境:黑客开始启动使用不受信任的代码的应用程序,试图破坏我们的“安全”。

黑客可以使用自己的安全管理器和安全类加载器创建自己的应用程序。它可以从类路径加载我们的代码并执行它,就像它是我们自己的应用程序一样。这样的话,他就可以破坏保险箱。

最佳答案

不,它对于其他 Java 代码并不安全。您可以从 Safe 实例中检索您的 secret ,如下所示:

Field field = safe.getClass().getDeclaredField("secret");
field.setAccessible(true);
String secret = (String) field.get(safe);

更新:如果您控制要隐藏 secret 的其他 Java 代码的加载,您可以使用自定义的 SecurityManagerClassLoader 来阻止对其进行访问。您需要控制它运行的环境,例如您限制访问的服务器。

但是,您编辑的问题提到该代码可以在任何桌面或设备上运行。在这种情况下,您实际上无法采取任何措施来保护 secret 免受其他几乎可以做任何事情的进程的影响。即使您在内存中对其进行加密,另一个进程也可以拦截 key ,甚至是传递的明文 secret 。

如果您无法控制需要确保安全的环境,那么您可能需要考虑采用不同的方法。也许您可以避免将 secret 完全存储在内存中?

关于java - secret 是否可以隐藏在提供访问凭据的 'safe' java 类中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58656876/

相关文章:

security - 在 IIS7.5 上安装 WordPress 时建议的文件系统权限是什么?

linux - 错误 register_security undefined

java - 克隆是如何在幕后工作的?

java.lang.Exception 与滚动您自己的异常

java - 如何理解是否创建了一个新的String对象

c++ - 嵌套类的问题。 "error: expected unqualified-id before ' {' token"

php - 如何获取调用类的名称(在 PHP 中)

security - ReCAPTCHA 如何工作?

java - Dozer MappingException NoSuchMethodException 初始化

java - 如何使用 staxmate 获取(和输出)命名空间前缀声明