2015-05-20 64 views
2

我試圖用私鑰簽名加密的消息並使用Java驗證它。這是我第一次使用加密和簽名,所以我不確定它應該如何工作,我有點卡在這裏。驗證總是返回false。無法驗證Android上的rsa簽名

在這裏,我對消息進行簽名:

public byte[] rsaSign (byte[] data) { 

byte[] cipherData = null; 

try { 

    RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(signModulus, signExponent); 
    KeyFactory fact = KeyFactory.getInstance("RSA"); 
    PrivateKey privKey = fact.generatePrivate(keySpec); 

    Signature s = Signature.getInstance("SHA1withRSA"); 
    s.initSign(privKey); 

    s.update(data); 

    return s.sign(); 
} 

return cipherData; 
} 

在這裏,我試圖驗證簽名:

public boolean rsaVerify (byte[] data, byte[] signature) { 

boolean success = false; 

try { 

    RSAPublicKeySpec keySpec = new RSAPublicKeySpec(signModulus, signPublicExponent); 
    KeyFactory fact = KeyFactory.getInstance("RSA"); 
    PublicKey pubKey = fact.generatePublic(keySpec); 

    Signature s = Signature.getInstance("SHA1withRSA"); 
    s.initVerify(pubKey); 

    s.update(data); 

    success = s.verify(signature); 

    return success; 

} 

return false; 
} 

任何人都可以看到的一個問題?密鑰在C#中生成並轉換爲Java中的BigIntegers。

+0

對我來說,這看起來很像一個圖書館相關的問題,如Ilmari所提到的那樣,在SO上會好很多。您應該強烈考慮遷移您的問題,因爲它很可能會在SO上得到解答。 – SEJPM

+0

我沒有發佈它,所以我沒有得到任何答案。我會考慮讓它自成體系並再次嘗試。謝謝! – user3685322

+0

@ user3685322:確保將輸入值發佈到任何構建signModulus,signExponent,signPublicExponent;問題可能在那裏。 – fgrieu

回答

2

簽名驗證失敗,因爲您在驗證方法中使用了不同的public key。 使用public key驗證與用於rsaSign()方法的private key一致的簽名。

希望這會幫助你。需要注意的是,這是public key與在簽名生成方法所使用的private key一致:

/** 
    * This method will sign message with RSA 2048 key 
    * @return Void 
    */ 
    public void rsaSign (String message) throws Exception { 
     //key generation 
     KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); 
     SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN"); 
     keyGen.initialize(2048, random); 

     KeyPair keyPair = keyGen.generateKeyPair(); 
     PrivateKey priv = keyPair.getPrivate(); 
     PublicKey pub = keyPair.getPublic(); 

     System.out.println("RSAPub key Mod for Sign/Verify : " + Helper.toHex(((RSAPublicKey)pub).getModulus().toByteArray())); 
     System.out.println("RSAPub key Exp for Sign/Verify : " + Helper.toHex(((RSAPublicKey)pub).getPublicExponent().toByteArray())); 

     //sign 
     Signature dsa = Signature.getInstance(signALG); 
     dsa.initSign(priv); 

     dsa.update(Helper.toByte(message)); 
     byte[] realSig = dsa.sign(); 
     System.out.println("RSA Sign-Data : " + Helper.toHex(realSig)); 
    } 


/** 
    * This method verify signature with RSA public key 
    * @param message The plain message 
    * @param rsaMOD RSA Public key Modulus in string 
    * @param rsaEXP RSA Public key Exponent in string 
    * @param rsaSignData Signature which will be verified 
    * @return true if verifications success, false otherwise 
    */ 
    public boolean rsaVerify(String message, String rsaMOD, String rsaEXP, String rsaSignData) throws Exception { 
     BigInteger modBigInteger = new BigInteger(Helper.toByte(rsaMOD)); 
     BigInteger exBigInteger = new BigInteger(Helper.toByte(rsaEXP)); 

     RSAPublicKeySpec spec = new RSAPublicKeySpec(modBigInteger, exBigInteger); 
     KeyFactory factory = KeyFactory.getInstance("RSA"); 
     PublicKey publicKey = factory.generatePublic(spec); 

     Signature signature = Signature.getInstance(signALG); 
     signature.initVerify(publicKey); 
     signature.update(Helper.toByte(message)); 

     return signature.verify(Helper.toByte(rsaSignData)); 
    } 
+0

編號RSAPublicKeySpec有參數,問題指出它們已經在C#中生成。 – fgrieu

+1

我認爲OP打破了密鑰對的一致性。 @fgrieu –

+0

我很喜歡這個新的介紹;我有[版本1的答案](http://crypto.stackexchange.com/revisions/25799/1)問題,因爲我沒有看到問題中的代碼是「_在驗證方法中生成新的公鑰_ 「 – fgrieu

0

你應該嘗試先在本地測試這些東西,用自己生成的密鑰對。如果失敗了,你的代碼是錯誤的 - 這是Java Signature的一個非常簡單的包裝,所以根本不可能。

您已經使用了完整的簽名算法規範,因此提供者的默認值在這裏不是問題。

然後在簽名生成/驗證之前通過在Hex或Base64中打印出來來檢查數據的正確性。如果失敗了,你會遇到I/O或編碼/解碼錯誤。編碼/解碼錯誤&字符串處理佔加密相關問題總數的約30%!

最後,您可以獲得並比較私鑰和公鑰的模數。如果模數不匹配,那麼您正在使用不同密鑰對的私鑰和公鑰,並且簽名驗證當然總是失敗。