|
13 | 13 | import java.util.regex.Pattern; |
14 | 14 |
|
15 | 15 | import junit.framework.TestCase; |
| 16 | +import org.bouncycastle.asn1.ASN1Encodable; |
| 17 | +import org.bouncycastle.asn1.DEROctetString; |
| 18 | +import org.bouncycastle.asn1.DERSequence; |
16 | 19 | import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; |
17 | 20 | import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; |
18 | 21 | import org.bouncycastle.crypto.AsymmetricCipherKeyPair; |
@@ -762,6 +765,85 @@ public void testPrivateKeyRejectsMalformedLength() |
762 | 765 | } |
763 | 766 | } |
764 | 767 |
|
| 768 | + public void testComponentLengthChecks() |
| 769 | + throws Exception |
| 770 | + { |
| 771 | + MLDSAKeyPairGenerator kpGen = new MLDSAKeyPairGenerator(); |
| 772 | + kpGen.init(new MLDSAKeyGenerationParameters(new SecureRandom(), MLDSAParameters.ml_dsa_44)); |
| 773 | + AsymmetricCipherKeyPair kp = kpGen.generateKeyPair(); |
| 774 | + MLDSAPrivateKeyParameters priv = (MLDSAPrivateKeyParameters)kp.getPrivate(); |
| 775 | + MLDSAPublicKeyParameters pub = (MLDSAPublicKeyParameters)kp.getPublic(); |
| 776 | + |
| 777 | + byte[][] parts = new byte[][]{ priv.getRho(), priv.getK(), priv.getTr(), priv.getS1(), priv.getS2(), priv.getT0(), priv.getT1(), priv.getSeed() }; |
| 778 | + String[] names = new String[]{ "rho", "K", "tr", "s1", "s2", "t0", "t1", "seed" }; |
| 779 | + |
| 780 | + // correct lengths are accepted, with and without the optional seed and t1 |
| 781 | + new MLDSAPrivateKeyParameters(MLDSAParameters.ml_dsa_44, parts[0], parts[1], parts[2], parts[3], parts[4], parts[5], parts[6], parts[7]); |
| 782 | + new MLDSAPrivateKeyParameters(MLDSAParameters.ml_dsa_44, parts[0], parts[1], parts[2], parts[3], parts[4], parts[5], null); |
| 783 | + |
| 784 | + for (int i = 0; i != parts.length; i++) |
| 785 | + { |
| 786 | + for (int delta = -1; delta <= 1; delta += 2) |
| 787 | + { |
| 788 | + byte[][] bad = new byte[parts.length][]; |
| 789 | + System.arraycopy(parts, 0, bad, 0, parts.length); |
| 790 | + bad[i] = Arrays.copyOf(parts[i], parts[i].length + delta); |
| 791 | + try |
| 792 | + { |
| 793 | + new MLDSAPrivateKeyParameters(MLDSAParameters.ml_dsa_44, bad[0], bad[1], bad[2], bad[3], bad[4], bad[5], bad[6], bad[7]); |
| 794 | + fail("no exception for " + names[i] + " of length " + bad[i].length); |
| 795 | + } |
| 796 | + catch (IllegalArgumentException e) |
| 797 | + { |
| 798 | + assertEquals("'" + names[i] + "' has invalid length", e.getMessage()); |
| 799 | + } |
| 800 | + } |
| 801 | + } |
| 802 | + |
| 803 | + byte[] rho = pub.getRho(); |
| 804 | + byte[] t1 = pub.getT1(); |
| 805 | + |
| 806 | + new MLDSAPublicKeyParameters(MLDSAParameters.ml_dsa_44, rho, t1); |
| 807 | + |
| 808 | + for (int delta = -1; delta <= 1; delta += 2) |
| 809 | + { |
| 810 | + try |
| 811 | + { |
| 812 | + new MLDSAPublicKeyParameters(MLDSAParameters.ml_dsa_44, Arrays.copyOf(rho, rho.length + delta), t1); |
| 813 | + fail("no exception for rho of length " + (rho.length + delta)); |
| 814 | + } |
| 815 | + catch (IllegalArgumentException e) |
| 816 | + { |
| 817 | + assertEquals("'rho' has invalid length", e.getMessage()); |
| 818 | + } |
| 819 | + |
| 820 | + byte[] badT1 = Arrays.copyOf(t1, t1.length + delta); |
| 821 | + try |
| 822 | + { |
| 823 | + new MLDSAPublicKeyParameters(MLDSAParameters.ml_dsa_44, rho, badT1); |
| 824 | + fail("no exception for t1 of length " + badT1.length); |
| 825 | + } |
| 826 | + catch (IllegalArgumentException e) |
| 827 | + { |
| 828 | + assertEquals("'t1' has invalid length", e.getMessage()); |
| 829 | + } |
| 830 | + |
| 831 | + // SEQUENCE { OCTET STRING rho, OCTET STRING t1 } public key form via PublicKeyFactory |
| 832 | + SubjectPublicKeyInfo spki = SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(pub); |
| 833 | + SubjectPublicKeyInfo badSpki = new SubjectPublicKeyInfo(spki.getAlgorithm(), |
| 834 | + new DERSequence(new ASN1Encodable[]{ new DEROctetString(rho), new DEROctetString(badT1) })); |
| 835 | + try |
| 836 | + { |
| 837 | + PublicKeyFactory.createKey(badSpki); |
| 838 | + fail("no exception for SEQUENCE encoded public key with t1 of length " + badT1.length); |
| 839 | + } |
| 840 | + catch (IllegalArgumentException e) |
| 841 | + { |
| 842 | + // expected |
| 843 | + } |
| 844 | + } |
| 845 | + } |
| 846 | + |
765 | 847 | private interface RejectionOperation |
766 | 848 | { |
767 | 849 | byte[] processSign(MLDSAPrivateKeyParameters privParams, byte[] msg) |
|
0 commit comments