2014-01-10 61 views
1

这是一个系统的存根,它可以在OpenSSL中使用AES 256 CBC生成密钥对。下面代码的目标是生成两个随机密钥,一个AES密钥和一些其他公共数据。 AES密钥将用于交换共享密钥。基于PBKDF的AES密钥的强度

声明:我不是密码学或安全系统方面的专家。我意识到危险,但这个练习的重点是学术兴趣。如果有新手错误或者完全不正确的危险错误,请指出来帮助我学习。

// The key_generator() will produce the following public keys in addition 
// to a couple of other private keys. 
// public_identifier 
// public_salt 
// public_composite_identifier 
// public_aes_key 

int key_generator(/*some args*/) 
{ 
    // Step 1 
    //Obtain public_identifier. Possibly a hashed value of an unique ASCII string. 
    unsigned char *public_identifier; 


    // Step 2 
    //Generate 256 bit private_primary_random_passkey which is secret. 
    //This random key is generated once and reused later. 
    unsigned char *private_primary_random_passkey; 

    if(RAND_bytes(private_primary_random_passkey, 256) == 0)  
     return FAILURE; 


    // Step 3 
    //Generate private_composite_identifier using public_identifier 
    //and private_primary_random_passkey. 
    //IMPORTANT - The method to obtain private_composite_identifier 
    //may be publicly known. 
    //The public_identifier is also publicly known but the 
    //private_primary_random_passkey is secret. 
    unsigned char *private_composite_identifier; 

    //<Some code for generating private_composite_identifier> 
    //..... 
    //</code> 


    // Step 4  
    //Generate temporary temp_private_aes_key and temp_private_aes_IV; 
    //NOTE - Used dummy vars wherever key length is required. 
    //Assume correct length is passed in. 

    int aes_rounds = 25000; 

    unsigned char *temp_private_aes_key; 
    unsigned char *temp_private_aes_IV; 

    if(EVP_BytesToKey(EVP_aes_256_cbc(), 
         EVP_sha512(), 
         private_composite_identifier, 
         private_primary_random_passkey, 
         private_composite_identifier_length/8, 
         aes_rounds, 
         temp_private_aes_key, 
         temp_private_aes_IV) == 0)  
     return FAILURE;  


    // Step 5 
    //Generate 128 bit random salt which is public. 
    unsigned char *public_salt; 

    if(RAND_bytes(public_salt, 128) == 0)  
     return FAILURE; 


    // Step 6 
    //Generate private_composite_identifier and public_composite_identifier 
    //using temp_private_aes_key and public_salt. 
    unsigned char *public_composite_identifier; 
    unsigned char *private_composite_identifier; 

    if(EVP_BytesToKey(EVP_aes_256_cbc(), 
         EVP_sha512(), 
         temp_private_aes_key, 
         public_salt, 
         temp_private_aes_key_length/8, 
         aes_rounds, 
         private_composite_identifier, 
         public_composite_identifier) == 0)  
     return FAILURE;  


    // Step 7 
    //Generate 128 bit private_secondary_random_passkey which is secret. 
    //This random key is generated once and reused later. 
    unsigned char *private_secondary_random_passkey; 

    if(RAND_bytes(private_secondary_random_passkey, 128) == 0)  
     return FAILURE; 

    unsigned char *private_aes_key; 
    unsigned char *public_aes_key; 

    if(EVP_BytesToKey(EVP_aes_256_cbc(), 
         EVP_sha512(), 
         private_composite_identifier, 
         private_secondary_random_passkey, 
         private_composite_identifier_length/8, 
         aes_rounds, 
         private_aes_key, 
        public_aes_key) == 0)  
     return FAILURE 
} 

这里是我的问题:

  • 如果一个RSA密钥对被用来替代AES密钥?为什么会比另一个更受欢迎?
  • 由于用于生成密钥对的密钥很长,随机生成和腌制,以后使用相同的AES/RSA密钥对是否安全?我了解彩虹表和其他措施的风险,但不是那些随随着三级密钥生成随机盐和密钥而减轻的问题?
  • 恶意攻击者可以使用公开可用的数据重新创建密钥对或破坏此系统的方式有哪些?
  • 您可以考虑阻止或增强此系统的其他任何要点。

谢谢你的时间。

+0

AES是对称的。 RSA是不对称的。 –

+0

@JonathonReinhart - 感谢您指出n00b错误。 :)如果在第7步中我们从可用信息生成一个RSA密钥对并且使用此密钥对进行未来加密,您是否可以重新考虑这些问题? –

回答

0

你真的进入密码学工程,Crypto Stack Exchange的人可能会更适合这些类型的设计问题。

此外,你缺少任何有用的答复很多细节。 (当问题更具实现性和特定性时,请回来)。 PBKDF的


强度基于AES密钥

一是称号。

这个问题与猜测密码一样困难,并且可能比以往数据泄露的数百万字列表更容易。也就是说,攻击者不会试图破坏AES密钥 - 他或她将尝试猜测用于派生密钥的密码。

要使用128位安全性密钥来加密AES-128密钥,需要密码中有128位熵。密码不是随机的,英文每个字母约有1.3位熵,因此预计AES-128会使用大约14位以上的密码。如果您键入AES-256,请使用28+字符的密码。


下面的代码的目的是生成两个随机口令的,AES密钥,以及其他一些公共数据。 AES密钥将用于交换共享密钥。

这里的目标是什么?创建安全频道?或者只是交换密钥?

通常您使用公钥传输或协议传输对称密钥或会话密钥。即:(1)使用Diffie-Hellman生成共享密钥(双方都添加到进程中的'密钥协议'),然后在共享密钥下传输对称会话密钥;或(2)使用RSA传输'主'对称会话密钥('密钥传输',因为一方产生密钥,在对方的RSA密钥下对其进行加密,然后将其发送给对等体)。

有基于共享密钥和口令认证密钥交换。 SSL/TLS有两个 - 预先共享密钥(PSK)和安全远程密码(SRP)。 PSK使用AES作为原语,SRP使用Diffie-Hellman。

PSK和SRP通常比DH和RSA更好,因为它们提供了(1)的相互认证和(2)信道绑定。根据你的陈述“AES密钥将被用来交换共享秘密”,PSK对你来说可能是完美的。但是,如果它们是一个不错的选择,它并不明显,因为我们不知道你在努力完成什么。


如果RSA密钥对可以用来代替AES密钥?为什么会比另一个更受欢迎?

这取决于您的问题域和您正在尝试做什么。

如果服务器有一个RSA公钥,然后你会使用Diffie-Hellman或RSA。如果你和服务器共享一个秘密,那么避免公开密钥的东西,并使用PSK或SRP。

的Diffie-Hellman和RSA在计算方面是昂贵的。它们通常用于交换或传输对称密码密钥。 RSA-2048可能需要4或500万条指令,并且会削弱性能。

对称密码的计算速度很快。它们用于大多数流量一次 Diffie-Hellman或RSA已完成。我们称之为批量加密,它们是脂肪。如果您有Ivy Bridge硬件,那么AES-NI可以为加密数据处理1个周期/字节。

当你读到这样nginx的Web服务器只能处理1000个SSL/TLS连接,您所看到的Diffie-Hellman和RSA的影响。一旦这些频道被设置并用于批量加密,它可以处理数千个加密的业务流。

以后使用相同的AES/RSA密钥对是否安全?

这些都是苹果和桔子。您通常长期使用RSA密钥对,而AES密钥仅限于会话。

通常,协议的每次运行应使用不同的参数。该协议也应该缺乏对称性,以便攻击者不能启动协议的第二个实例,然后让您的服务器回答第一个实例与第二个实例上存在的问题。


我理解彩虹表和其他措施的风险,但不与后面三级密钥生成的随机盐和键缓解这些问题?

这取决于你的问题域和你正在做什么。我们无法真正回答,因为我们不知道你在努力完成什么。

请参阅John Steven在OWASP的Password Storage Cheat Sheet。他会带你通过威胁模型并解释系统的各个部分。详细治疗可在Secure Password Storage


什么是在恶意攻击者可以重新创建密钥对或使用公开的数据打破了这种系统的方法呢?

这取决于你的问题域和你正在做什么。我们无法真正回答,因为我们不知道你在努力完成什么。

密钥管理是密码中最难的部分,而我们看到的是一个真空:

int key_generator(/*some args*/) 

你需要充分详细的所有参数,你如何管理它们,以及如何使用它们。


,你能想到的任何其他点来阻止或增强该系统。

这跳出:三个电话RAND_byesEVP_BytesToKey。通常,您这样做:

byte[] master = Random(16) // or 32, or however many you need 
byte[] key1 = Derive(master, "<some usage>", <other distinguishing information>) 
byte[] key2 = Derive(master, "<some usage>", <other distinguishing information>) 
byte[] key3 = Derive(master, "<some usage>", <other distinguishing information>) 

master可能来自密钥交换或密钥协议。

key1,key2key3可能不同,因为(1)调用之间的使用情况不同,以及(2)额外的区分信息在对等点之间不同。

Derive可以是HMACCMAC,并且包括KDF的元素。同样看看HKDF,这是'扩展然后提取'算法的最新技术。

+0

感谢您的详细回复!第一个目标:这是建立一个系统,客户可以确定性(重新)生成公钥对,这些公钥将用于使用现有密钥对交换数据。 密码不一定要用英文。当客户希望交换数据时,十六进制密钥将被重新输入以重新生成密钥对。这就是密码在存根中随机生成并呈现给注册客户端的原因。在初始生成密钥之后,每个客户端都将拥有一些与公钥和公共盐相关的唯一标识符。 –

+0

我理解你对使用派生方法的观点,而不是对EVP_BytesToKey使用单独调用(RAND_bytes调用仅用于初始客户端注册)。我将努力进行充实的测试实施,记住您记住的要点并重新获得回应。这就是说,我一直无法找到在OpenSSL for C/C++中确定性地从给定种子(本例中是256位随机种子)创建RSA密钥对(或任何其他非对称密钥对)的好例子。如果你或其他人能指出我这样一个例子,那将是非常有用的。 –