【问题标题】:make MessageDigest and Cipher equivalent to java.security.Signature使 MessageDigest 和 Cipher 等效于 java.security.Signature
【发布时间】:2016-04-16 22:48:35
【问题描述】:

我想使用 RSA 作为密码算法和 SHA-1 作为哈希函数来实现我自己的签名函数,为此我实现了这两个函数:

public byte[] mySign(byte[] aMessage){
    try{
        // get an instance of a cipher with RSA with ENCRYPT_MODE
        // Init the signature with the private key
          Cipher cipher = Cipher.getInstance("RSA");
          cipher.init(Cipher.ENCRYPT_MODE, this.thePrivateKey);

        // get an instance of the java.security.MessageDigest with sha1
             MessageDigest meassDs = MessageDigest.getInstance("SHA-1");

        // process the digest
             meassDs.update(aMessage);
             byte[] digest = meassDs.digest();

            byte [] signature = cipher.doFinal(digest);

        // return the encrypted digest
        return signature;

    }catch(Exception e){
        System.out.println(e.getMessage()+"Signature error");
        e.printStackTrace();
        return null;
    }

}



public boolean myCheckSignature(byte[] aMessage, byte[] aSignature, PublicKey aPK){
    try{
        // get an instance of a cipher with RSA with DECRYPT_MODE
        // Init the signature with the public key
          Cipher cipher = Cipher.getInstance("RSA");
          cipher.init(Cipher.DECRYPT_MODE, aPK);

        // decrypt the signature
             byte [] digest1 = cipher.doFinal(aSignature);

        // get an instance of the java.security.MessageDigest with sha1
             MessageDigest meassDs = MessageDigest.getInstance("SHA-1");

        // process the digest
             meassDs.update(aMessage);
             byte[] digest2 = meassDs.digest();

        // check if digest1 == digest2
        if (digest1 == digest2)
        return true;
        else
            return false;

    }catch(Exception e){
        System.out.println("Verify signature error");
        e.printStackTrace();
        return false;
    }
}   

然后当我使用这些函数时,我总是得到 false 作为结果,这意味着我的函数不能正常工作:

byte[] message = "hello world".getBytes();
byte[] signature;

signature = mySign(message );
boolean bool = myCheckSignature(message , signature, thePublicKey);
System.out.println(bool);

【问题讨论】:

标签: java rsa digital-signature sha1 java-security


【解决方案1】:

根据您的要求

使用 java.security.Signature 的替代方法来实现创建签名的方法

作为一个整体是有问题的(如您的问题的 cmets 中所述),您的解决方案可以改进。

尤其是您的myCheckSignature 代码中有错误:

// check if digest1 == digest2
if (digest1 == digest2)
    return true;
else
    return false;

(digest1 == digest2) 检查您是否有相同的数组对象,而不是检查您是否有两个内容相同的数组。

你真正想做的是

if (Arrays.equals(digest1, digest2))
    return true;
else
    return false;

或更紧凑

return Arrays.equals(digest1, digest2);

Arrays 是包java.util 中的一个实用程序类。


顺便说一句,你做到了

byte[] message = "hello world".getBytes();

getBytes 不明确选择字符编码可能会导致在不同平台或不同 Java 版本上产生不同的结果。在这种情况下不应该发生的事情!

【讨论】:

  • 如果 OP 将使用您的建议来创建自己的签名,他可能应该至少使用 SHA-256 而不是 SHA-1。从 caot 的链接中获取,甚至使用 bcrypt/PBKDF2 可能会更好(我没有使用此的经验)。
  • @TT。我完全同意...他根本不应该创建他自己的。特别是我指出的问题对于 Java 101 以外的每个人来说都应该是显而易见的,所以他最终will make a major security mistake 的机会很高。
  • 是的,他已经犯了一些严重错误,而且他确实会犯更多错误。
  • 关于你对getBytes的最后陈述:这应该是"Hello World".getBytes( "UTF-8" )。
  • 非常感谢@mkl 现在它对我来说很好用,我知道这是一个愚蠢的错误,实际上是因为我不熟悉 java
猜你喜欢
  • 2010-10-05
  • 1970-01-01
  • 2014-05-15
  • 1970-01-01
  • 2021-04-05
  • 1970-01-01
  • 2012-03-02
  • 2019-04-11
  • 2021-12-16
相关资源
最近更新 更多