一个秘密可以隐藏在提供访问凭据的“安全”java类中吗? [英] Can a secret be hidden in a 'safe' java class offering access credentials?

查看:193
本文介绍了一个秘密可以隐藏在提供访问凭据的“安全”java类中吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个头脑风暴的问题,关于什么是可能在Java(或不)。我想知道是否可以隐藏一个类中的秘密,并阻止再次访问使用Java代码或其任何功能(安全,反射,序列化,类加载器,您的名称-it ...)。



这是我到目前为止所想的:

  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凭据getCredential(String user){
//下面的测试仅仅是为了说明意图...
if accepted.equals(user)){
return new Credentials(user);
} else {
return null;
}
}

public String gimmeTheSecret(Credentials cred){
if(this.validCertificates.get(cred.user)== cred){
返回秘密;
} else {
return null;
}
}

private void writeObject(ObjectOutputStream stream)throws IOException {
throw new RuntimeException(No no no no no no no !!!);
}

}

可以改进吗?应该改进吗?在安全类中锁定密码的想法不可能实现?



EDIT



相关性:



有些人质疑我在这里提出的问题的相关性。虽然我要求一个一般性的问题,以触发一个开放的对话,这个类有一个非常具体的应用:




  • 如果我想解密一些消息,我需要加载一个私钥数据到类。如果我不能阻止其他Java代码访问它,那么创建一个安全系统是不可能的。当然,如果我想解密一个消息,我宁愿在课堂上做,而不是放弃秘密,但仍然,安全必须保持不可破坏。



澄清:




  • 类的实例仅在运行时创建

  • 代码可以在网络服务器应用程序或任何桌面或设备应用程序中运行

  • 该类仅用于在运行时存储秘密,在内存中,没有计划持久化(对于持久化,可以/应该使用经典加密技术)



/ em>




  • 要在Java应用程序中实现安全性,应该设置一个SecurityManager实例,

  • 此应用程序可以使用安全类加载器加载不受信任的代码,并为加载的类分配一个保护域。此域 不应 包括RuntimePermission(setSecurityManager)。

  • 不受信任的代码可以尝试更改SecurityManager,安全类加载器未授予setSecurityManager权限,将抛出SecurityException。



解决的问题: / p>

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




  • 受控环境:我们开始使用不受信任的代码尝试打破我们的安全的应用程序。



如果我们设置正确的SecurityManager禁用任何加载的不受信任的代码的反射和限制权限,


  • 不受控制的环境:Hacker开始使用不受信任的代码试图破坏我们的安全。


黑客可以使用自己的安全管理器和安全类加载器创建自己的应用程序。它可以从类路径加载我们的代码,并执行它,就像它是我们自己的应用程序。




解决方案

不,它与其他Java代码不安全。您的秘密可以从安全的实例中检索,如下所示:

 字段字段= safe.getClass()。getDeclaredField(secret); 
field.setAccessible(true);
String secret =(String)field.get(safe);

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



但是,您修改的问题表明代码可以在任何台式机或设备上运行。在这种情况下,你真的没有什么可以做的,以保护秘密,从其他进程,可以做任何事情。即使你在内存中加密,另一个进程也可以拦截密钥,甚至是明文秘密,因为它传递。



如果你不控制你需要的环境某些东西要安全,那么你可能需要考虑一个不同的方法。也许你可以避免把内存中的秘密存储在一起?


This is a brainstorming question about what's possible in Java (or not). I want to know if it is possible to hide a secret within a class and prevent anymore from accessing it using Java code or any of its feature only (security, reflexion, serialization, class loaders, you-name-it...).

Here is what I have in mind so far:

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!!!");
    }

}

Can it be improved? Should it be improved? Is the idea of locking a secret in a safe class impossible to achieve?

EDIT

Relevance:

Some people question the relevance of the issue I am raising here. Although I am asking a general question in order to trigger an open conversation, there is a very concrete application to this class:

  • If I want to decrypt some messages, I need to load a private key data into a class. If I can't prevent other Java code from accessing it, then it is impossible to create a secure system. Of course, if I want to decrypt a message, I should rather do it in the class than giving away the secret, but still, the safe has to remain unbreakable.

Clarification:

  • Instances of the class are only created at runtime, not at compile time
  • Code can run in web server applications or any desktop or device applications
  • The class is only used to store a secret at runtime, in memory, no plans to persist it (for persistence, one can/should use classic encryption techniques)

Facts:

  • To implement security in a Java application, one should set a SecurityManager instance where checking methods are overridden as needed
  • This application can load untrusted code with secure class loaders and assign a protection domain for the classes it loads. This domain should not include a RuntimePermission("setSecurityManager").
  • Untrusted code can try to change the SecurityManager, but since the Secure Class Loader did not grant the setSecurityManager permission, a SecurityException will be thrown.

Solved issues:

Regarding the execution environment, we need to distinguish two cases:

  • Controlled environment: We get to start the application that will use untrusted code trying to break our 'safe'.

If we set a proper SecurityManager disabling reflection and restricting permissions on any loaded untrusted code, then our secret is safe.

  • Uncontrolled environment: Hacker gets to start the application which uses untrusted code trying to break our 'safe'.

The hacker can create his own application with its own security manager and Secure Class loader. It could load our code from the classpath and execute it as if it were our own application. In this case, he could break the safe.

解决方案

No, it's not safe from other Java code. Your secret could be retrieved from an instance of Safe like this:

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

Update: If you control the loading of the other Java code that you want to hide the secret from you can probably use a custom SecurityManager or ClassLoader to prevent access to it. You need to control the environment that this runs in to work though, e.g. a server you restrict access to.

Your edited question however mentions that the code can run on any desktop or device. In that case there's really nothing you can do to protect the secret from other processes that could do just about anything. Even if you encrypt it in memory another process can just intercept the key or even the plaintext secret as its passed around.

If you don't control the environment that you need something to be secure in then you likely need to consider a different approach. Perhaps you can avoid storing the secret in memory altogether?

这篇关于一个秘密可以隐藏在提供访问凭据的“安全”java类中吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆