/** * Check the digital signature. As very large documents can be signed, we represent them as * streams. The document can be way too large to load the whole into memory, so implementations * should calculate the signature by reading portions of it from the stream. * <p> * The method must not throw exception if the signature is bad. e.g. improper, has wrong * structure and so on. Instead, it must return false. * * @param input source data * @param signature signature to check * * @return true if the signature is valid, false if not. * @throws IOException failed to read the input stream (including empty stream, EOF at start) */ public boolean checkSignature(InputStream input, byte[] signature, HashType hashType) throws IOException, IllegalStateException { return checkSignature(input, signature, hashType, MAX_SALT_LENGTH); }
/** * Encrypt data of the string using UTF-8 encoding * * @param data to encrypt * @return encrypted data * @throws EncryptionError */ public byte[] encrypt(String data) throws EncryptionError { return encrypt(data.getBytes()); } }
/** * Test {@link RSAOAEPPublicKey#updateFromHash} on success scenarios, * using RSA spec vectors. */ @Test public void updateFromHashGoodRSASpec() throws Exception { Map mapRSA = new HashMap<String, Object>() {{ put("n", oaepSpec.n); put("e", oaepSpec.e); put("hash", "SHA-1"); put("mgf1Hash", "SHA-1"); }}; AbstractPublicKey rsaPublicKey = new RSAOAEPPublicKey(); rsaPublicKey.updateFromHash(mapRSA); // We've read the public key from hash; // but, to test it over the RSA spec vectors, // we need to hack into the state.rng (and substitute it with our custom one), // even though it is declared as final. RSAOAEPPublicKey.State state = ((RSAOAEPPublicKey) rsaPublicKey).state; Field rngField = RSAOAEPPublicKey.State.class.getDeclaredField("rng"); rngField.setAccessible(true); rngField.set(state, oaepSpec.getRandSeed()); // Now we can even test the encryption on the RSA spec vectors. assertTrue(rsaPublicKey.isInitialized()); assertEquals(rsaPublicKey.getBitStrength(), 1024); ((RSAOAEPPublicKey) rsaPublicKey).resetEncryptor(); assertArrayEquals(rsaPublicKey.encrypt(oaepSpec.M), oaepSpec.C); }
/** * Test {@link RSAOAEPPublicKey} basic methods: * {@link RSAOAEPPublicKey#canEncrypt}, * {@link RSAOAEPPublicKey#getBitStrength}, * {@link RSAOAEPPublicKey#isInitialized}, * {@link RSAOAEPPublicKey#algorithmTag}. */ @Test public void basicMethods() throws Exception { AbstractPublicKey goodPublicKey1 = oaepSpec.getPublicKey(); assertEquals(goodPublicKey1.canEncrypt(), true); assertEquals(goodPublicKey1.getBitStrength(), 1024); assertEquals(goodPublicKey1.isInitialized(), true); assertEquals(goodPublicKey1.algorithmTag(), "r1"); }
assertTrue(rsaPublicKey.isInitialized()); assertEquals(rsaPublicKey.getBitStrength(), 1024); ((RSAOAEPPublicKey) rsaPublicKey).resetEncryptor(); assertArrayEquals(rsaPublicKey.encrypt(oaepSpec.M), oaepSpec.C);
/** * Test {@link RSAOAEPPublicKey#updateFromHash} on success scenarios, * on some sample vector where some data is default. */ @Test public void updateFromHashGoodSampleWithDefaultData() throws Exception { Map map = new HashMap<String, byte[]>() {{ put("n", Hex.decode("ad9a9c60d98ee0463f7629675703b23ed4b330ae851c278233a105d120713a6286945f71e6d46f8d9ad0d30e4551a5de8bb9d9a74750645c579c3902266aefecdc111e032048a84ea76220bc570c5cade835909546029a65baff6d29c4207c4b918ff524d80812ecfda388c8cd4ac1878699193040a075bcd4b3987fcbe749bbdfc44665616ff6789f7363b765eb72530e17698d9bd778fd476b3aefc6bce6cec5d44c52e4acb8981390af5174bcb84e3a17e719ba58b93d13bc929d48dbb78d8f5d85002b281159f10e4b801627d3f8acfab100bd2c6380d04ca08bcb9227d84fe282150d71f0660fbbff744800dc6466d47cf5c22d03bac3c0d73dac9bc2a020cb51ca229448c317e73e8f97125a5ff8568b6af0b493b822096021ee1c7eed6d0ad6164e0798055b3b24404983728c2923e9d959c655b2e138650de0ffb5a74b7e612e764fb0e3104ceb5b8df3aaae80a57dbb8f7c305503a51253fc0f1f7a82057c6af262a484f7243f69046c946fd8fc93d71ad90315bfb42467c826dad0253ec83e0ed9b3fa3dca8162f5c691a9e91f69b890b04138de12e0657d8b044f77b455d3ff4257c52e1a33e6792c7a64d9bd8009d79a5fe73dadcd9a80a2f5f51b1c80e6ee41928f0b08a1e9f5d552ec2e5380de554dac97d76aeac2000c4f992eb582532448641d89bbee2334e51d76a3952119093eb5baa545bf1beabd49f5")); put("e", Hex.decode("010001")); // Not putting any of the optional fields. }}; AbstractPublicKey publicKey = new RSAOAEPPublicKey(); publicKey.updateFromHash(map); assertTrue(publicKey.isInitialized()); assertEquals(publicKey.getBitStrength(), 4096); RSAOAEPPublicKey.State publicKeyState = ((RSAOAEPPublicKey) publicKey).state; assertEquals(publicKeyState.oaepHashType, HashType.SHA1); assertEquals(publicKeyState.mgf1HashType, HashType.SHA1); }
assertTrue(publicKey.isInitialized()); assertEquals(publicKey.getBitStrength(), 4096);
AbstractPublicKey publicKeyNoData = new RSAOAEPPublicKey(); try { publicKeyNoData.updateFromHash(badMapNoData); } catch (Exception e) { assertTrue(e instanceof Hashable.Error); assertFalse(publicKeyNoData.isInitialized()); AbstractPublicKey publicKeyPartialData = new RSAOAEPPublicKey(); try { publicKeyNoData.updateFromHash(badMapPartialData); } catch (Exception e) { assertTrue(e instanceof Hashable.Error); assertFalse(publicKeyPartialData.isInitialized()); AbstractPublicKey publicKeyBadString = new RSAOAEPPublicKey(); try { publicKeyNoData.updateFromHash(badMapBadString); } catch (Exception e) { assertTrue(e instanceof Hashable.Error); assertFalse(publicKeyBadString.isInitialized());
/** * Test {@link RSAOAEPPublicKey#toHash}. */ @Test public void toHash() throws Exception { // Test sample RSA vectors. AbstractPublicKey rsaPublicKey = oaepSpec.getPublicKey(); Map mapRSA = rsaPublicKey.toHash(); assertArrayEquals((byte[]) mapRSA.get("n"), oaepSpec.n); assertArrayEquals((byte[]) mapRSA.get("e"), oaepSpec.e); assertFalse(mapRSA.containsKey("mgf1Hash")); // SHA-1 is the default value // Test random public key. AbstractPublicKey goodPublicKey1 = new RSAOAEPPublicKey( BigIntegers.asUnsignedByteArray(randomPublicKey1.getModulus()), BigIntegers.asUnsignedByteArray(randomPublicKey1.getExponent()), HashType.SHA512, HashType.SHA512, new SecureRandom()); Map map1 = goodPublicKey1.toHash(); assertArrayEquals((byte[]) map1.get("n"), BigIntegers.asUnsignedByteArray(randomPublicKey1.getModulus())); assertArrayEquals((byte[]) map1.get("e"), BigIntegers.asUnsignedByteArray(randomPublicKey1.getExponent())); assertEquals(map1.get("mgf1Hash"), "SHA-512"); }
/** * Test {@link RSAOAEPPublicKey#updateFromHash} on success scenarios, * on some sample vector. */ @Test public void updateFromHashGoodSample() throws Exception { Map map = new HashMap<String, Object>() {{ put("n", Hex.decode("ad9a9c60d98ee0463f7629675703b23ed4b330ae851c278233a105d120713a6286945f71e6d46f8d9ad0d30e4551a5de8bb9d9a74750645c579c3902266aefecdc111e032048a84ea76220bc570c5cade835909546029a65baff6d29c4207c4b918ff524d80812ecfda388c8cd4ac1878699193040a075bcd4b3987fcbe749bbdfc44665616ff6789f7363b765eb72530e17698d9bd778fd476b3aefc6bce6cec5d44c52e4acb8981390af5174bcb84e3a17e719ba58b93d13bc929d48dbb78d8f5d85002b281159f10e4b801627d3f8acfab100bd2c6380d04ca08bcb9227d84fe282150d71f0660fbbff744800dc6466d47cf5c22d03bac3c0d73dac9bc2a020cb51ca229448c317e73e8f97125a5ff8568b6af0b493b822096021ee1c7eed6d0ad6164e0798055b3b24404983728c2923e9d959c655b2e138650de0ffb5a74b7e612e764fb0e3104ceb5b8df3aaae80a57dbb8f7c305503a51253fc0f1f7a82057c6af262a484f7243f69046c946fd8fc93d71ad90315bfb42467c826dad0253ec83e0ed9b3fa3dca8162f5c691a9e91f69b890b04138de12e0657d8b044f77b455d3ff4257c52e1a33e6792c7a64d9bd8009d79a5fe73dadcd9a80a2f5f51b1c80e6ee41928f0b08a1e9f5d552ec2e5380de554dac97d76aeac2000c4f992eb582532448641d89bbee2334e51d76a3952119093eb5baa545bf1beabd49f5")); put("e", Hex.decode("010001")); put("mgf1Hash", "SHA-512"); }}; AbstractPublicKey publicKey = new RSAOAEPPublicKey(); publicKey.updateFromHash(map); assertTrue(publicKey.isInitialized()); assertEquals(publicKey.getBitStrength(), 4096); RSAOAEPPublicKey.State publicKeyState = ((RSAOAEPPublicKey) publicKey).state; assertEquals(publicKeyState.oaepHashType, HashType.SHA1); /* Default for now */ assertEquals(publicKeyState.mgf1HashType, HashType.SHA512); }
/** * Test {@link RSAOAEPPrivateKey#updateFromHash} on success scenarios, * on some sample vector. */ @Test public void updateFromHashGoodSample() throws Exception { Map map = new HashMap<String, Object>() {{ put("e", Hex.decode("010001")); put("p", Hex.decode("d4f56e648a7fe26ab052144abfd9a9cdb3ebf220ac05c3e3eb13e42c245ab0578e185a8782bf9b4c1fcc1f577a01cf9c86afef7b4fbb22ecf4fee4409f94c40da7527e0a084ae274494826a7352de4611d36b21bd3d43b4684d997dffff76765b2033a2dd949ccc5521bf1b2889c75a4ce5ce7eb09269dfeaa1f859449c4f359fcbbfc6a00593c1948665c494e7c7edd185c541a7709de5e0528345d0fc31bd214b4d36a7f96cea8fc003730fbeff97bb14267c14dad794d4f949a65fa10fcbc27d1df170128c42d294161ccdaec5e4886da42920d4f6d89dad7a038625111cd75f5d0268009d4fed07adb08da146729e3bf8e882646ad97df0a1e9391656951")); put("q", Hex.decode("c7524e21b6d44fe1e7467168b5888047216584821d4b12370f5ca42eefdf729c9f328fe4eaad06ae52aff40bf099d5e8383b34a6a5ea6d52fadf1178546b7afa48eee25801015fe174294a59c0f3fe24f8c3dcdc1572c96b602235e4c26e0fa85c2e9852f529574afb7ccc53ba47c6705de1170bd5b41cd8ca80efd1c324e1a5091a0a5a895d00b857185fd73fd284da14503b6b48a5ee165ce981732ae163d21ae4426204bb8a7e23c6793d4e9c9501a57abbf5457f745ff62e78d8bb250fe41bec2b3c6f77e64876a1d63d0b19ead7e393c7507358b5dbc4ce2c21554c00aa8e8d38c78e72ce0ed306e9c3ae0cd4cc1e92842caf7b70e883daf43b0cf25267")); put("mgf1Hash", "SHA-512"); }}; AbstractPrivateKey privateKey = new RSAOAEPPrivateKey(); privateKey.updateFromHash(map); AbstractPublicKey publicKey = privateKey.getPublicKey(); assertTrue(privateKey.isInitialized()); assertEquals(privateKey.getBitStrength(), 4096); // Also test that the public key counterpart is also deserialized properly // and is capable of encrypting the data (after deserialization) as needed. assertTrue(publicKey.isInitialized()); assertEquals(publicKey.getBitStrength(), 4096); RSAOAEPPublicKey.State publicKeyState = ((RSAOAEPPublicKey)publicKey).state; assertEquals(publicKeyState.oaepHashType, HashType.SHA1); // Default assertEquals(publicKeyState.mgf1HashType, HashType.SHA512); RSAOAEPPrivateKey.State privateKeyState = ((RSAOAEPPrivateKey)privateKey).state; assertEquals(privateKeyState.oaepHashType, HashType.SHA1); // Default assertEquals(privateKeyState.mgf1HashType, HashType.SHA512); }
/** * Test {@link RSAOAEPPublicKey#toHash} where some data is default. */ @Test public void toHashWithDefaultData() throws Exception { // Test random public key. AbstractPublicKey goodPublicKey1 = new RSAOAEPPublicKey( BigIntegers.asUnsignedByteArray(randomPublicKey1.getModulus()), BigIntegers.asUnsignedByteArray(randomPublicKey1.getExponent()), HashType.SHA1, HashType.SHA1, new SecureRandom()); Map map1 = goodPublicKey1.toHash(); assertArrayEquals((byte[]) map1.get("n"), BigIntegers.asUnsignedByteArray(randomPublicKey1.getModulus())); assertArrayEquals((byte[]) map1.get("e"), BigIntegers.asUnsignedByteArray(randomPublicKey1.getExponent())); // With the default values (SHA-256 for hash, SHA-1 for MGF1), // hash and mgf1Hash fields should be missing from the hash. assertFalse(map1.containsKey("hash")); assertFalse(map1.containsKey("mgf1Hash")); }
/** * @param data to check the signature against. * @param signature signature to check * @return true if the signature is correct. */ public boolean checkSignature(String data, byte[] signature, HashType hashType) { return checkSignature(data.getBytes(), signature, hashType); }
/** * Test {@link RSAOAEPPublicKey#encrypt}. */ @Test public void encrypt() throws Exception { // Test on RSA vectors. AbstractPublicKey rsaPublicKey = oaepSpec.getPublicKey(); ((RSAOAEPPublicKey) rsaPublicKey).resetEncryptor(); assertArrayEquals(rsaPublicKey.encrypt(oaepSpec.M), oaepSpec.C); }
Map mapPrivate4096 = randomPrivateKey4096.toHash(), mapPublic4096 = randomPublicKey4096.toHash(); RSAPrivateCrtKeyParameters privateKeyParameters4096 = ((RSAOAEPPrivateKey) randomPrivateKey4096).state.keyParameters;
/** * @param input to check the signature against. * @param signature signature to check * @param hashType type of the hash function used to create the signature * @return true if the signature is correct. */ public boolean checkSignature(byte[] input, byte[] signature, HashType hashType) { try { return checkSignature(new ByteArrayInputStream(input), signature, hashType, MAX_SALT_LENGTH); } catch (IOException e) { return false; } }
/** * Test {@link RSAOAEPPrivateKey#getPublicKey}. */ @Test public void getPublicKey() throws Exception { AbstractPublicKey randomPublicKey4096 = randomPrivateKey4096.getPublicKey(); assertTrue(randomPublicKey4096 instanceof RSAOAEPPublicKey); AbstractPrivateKey rsaPrivateKey = oaepSpec.getPrivateKey(); AbstractPublicKey rsaPublicKey = rsaPrivateKey.getPublicKey(); ((RSAOAEPPublicKey) rsaPublicKey).resetEncryptor(); assertArrayEquals(rsaPublicKey.encrypt(oaepSpec.M), oaepSpec.C); }
Map mapPrivate4096SHA256 = randomPrivateKey4096SHADefault.toHash(), mapPublic4096SHA256 = randomPublicKey4096SHA256.toHash(); RSAPrivateCrtKeyParameters privateKeyParameters4096SHA256 = ((RSAOAEPPrivateKey) randomPrivateKey4096SHADefault).state.keyParameters;
/** * @param input to check the signature against. * @param signature signature to check * @param hashType type of the hash function used to create the signature * @return true if the signature is correct. */ public boolean checkSignature(byte[] input, byte[] signature, HashType hashType, int saltLength) { try { return checkSignature(new ByteArrayInputStream(input), signature, hashType, saltLength); } catch (IOException e) { return false; } }
assertArrayEquals(rsaPrivateKey.decrypt(oaepSpec.C), oaepSpec.M); ((RSAOAEPPublicKey) rsaPublicKey).resetEncryptor(); assertArrayEquals(rsaPublicKey.encrypt(oaepSpec.M), oaepSpec.C); rng.nextBytes(message); byte[] encrypted = randomPublicKey.encrypt(message), decrypted = randomPrivateKey.decrypt(encrypted); assertArrayEquals(decrypted, message);