|
19 | 19 | import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; |
20 | 20 | import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; |
21 | 21 | import org.bouncycastle.crypto.AsymmetricCipherKeyPair; |
| 22 | +import org.bouncycastle.crypto.CipherParameters; |
22 | 23 | import org.bouncycastle.crypto.CryptoException; |
| 24 | +import org.bouncycastle.crypto.DataLengthException; |
23 | 25 | import org.bouncycastle.crypto.Signer; |
24 | 26 | import org.bouncycastle.crypto.generators.MLDSAKeyPairGenerator; |
25 | 27 | import org.bouncycastle.crypto.params.MLDSAKeyGenerationParameters; |
26 | 28 | import org.bouncycastle.crypto.params.MLDSAParameters; |
27 | 29 | import org.bouncycastle.crypto.params.MLDSAPrivateKeyParameters; |
28 | 30 | import org.bouncycastle.crypto.params.MLDSAPublicKeyParameters; |
| 31 | +import org.bouncycastle.crypto.params.ParametersWithContext; |
29 | 32 | import org.bouncycastle.crypto.params.ParametersWithRandom; |
30 | 33 | import org.bouncycastle.crypto.signers.HashMLDSASigner; |
31 | 34 | import org.bouncycastle.crypto.signers.MLDSASigner; |
@@ -710,6 +713,60 @@ public void testHashExternalMu() |
710 | 713 | } |
711 | 714 | } |
712 | 715 |
|
| 716 | + public void testCalculateMuVerify() |
| 717 | + throws Exception |
| 718 | + { |
| 719 | + MLDSAKeyPairGenerator kpGen = new MLDSAKeyPairGenerator(); |
| 720 | + kpGen.init(new MLDSAKeyGenerationParameters(new SecureRandom(), MLDSAParameters.ml_dsa_65)); |
| 721 | + AsymmetricCipherKeyPair kp = kpGen.generateKeyPair(); |
| 722 | + |
| 723 | + byte[][] messages = { new byte[0], Strings.toByteArray("Hello World!") }; |
| 724 | + byte[][] contexts = { null, Strings.toByteArray("context") }; |
| 725 | + |
| 726 | + for (int c = 0; c != contexts.length; c++) |
| 727 | + { |
| 728 | + for (int m = 0; m != messages.length; m++) |
| 729 | + { |
| 730 | + byte[] message = messages[m]; |
| 731 | + CipherParameters priv = contexts[c] == null ? (CipherParameters)kp.getPrivate() : new ParametersWithContext(kp.getPrivate(), contexts[c]); |
| 732 | + CipherParameters pub = contexts[c] == null ? (CipherParameters)kp.getPublic() : new ParametersWithContext(kp.getPublic(), contexts[c]); |
| 733 | + |
| 734 | + MLDSASigner signer = new MLDSASigner(); |
| 735 | + signer.init(true, priv); |
| 736 | + signer.update(message, 0, message.length); |
| 737 | + byte[] mu = signer.generateMu(); |
| 738 | + signer.update(message, 0, message.length); |
| 739 | + byte[] signature = signer.generateSignature(); |
| 740 | + |
| 741 | + MLDSASigner verifier = new MLDSASigner(); |
| 742 | + verifier.init(false, pub); |
| 743 | + verifier.update(message, 0, message.length); |
| 744 | + assertTrue("mu rejected, message length " + message.length, verifier.verifyMu(mu)); |
| 745 | + |
| 746 | + byte[] flipped = Arrays.clone(mu); |
| 747 | + flipped[0] ^= 1; |
| 748 | + verifier.update(message, 0, message.length); |
| 749 | + assertFalse(verifier.verifyMu(flipped)); |
| 750 | + |
| 751 | + // checking a mu must leave the verifier able to check an ordinary signature |
| 752 | + verifier.update(message, 0, message.length); |
| 753 | + assertTrue(verifier.verifySignature(signature)); |
| 754 | + |
| 755 | + try |
| 756 | + { |
| 757 | + verifier.verifyMu(new byte[3]); |
| 758 | + fail("short mu accepted"); |
| 759 | + } |
| 760 | + catch (DataLengthException e) |
| 761 | + { |
| 762 | + assertEquals("mu value must be 64 bytes", e.getMessage()); |
| 763 | + } |
| 764 | + verifier.update(message, 0, message.length); |
| 765 | + assertTrue(verifier.verifyMu(mu)); |
| 766 | + } |
| 767 | + } |
| 768 | + } |
| 769 | + |
713 | 770 | public void testMLDSARejection() |
714 | 771 | throws Exception |
715 | 772 | { |
|
0 commit comments