/** * Check role is allowed to keys * * @param keys is set of keys * @return true if role is allowed to keys */ @Override public boolean isAllowedForKeys(Set<? extends AbstractKey> keys) { if(!super.isAllowedForKeys(keys)) { return false; } boolean allMatch1 = anonymousIds.stream().allMatch(anonId -> keys.stream().anyMatch(key -> { try { return key.matchAnonymousId(anonId.getBytes()); } catch (IOException e) { return false; } })); boolean allMatch2 = keyRecords.values().stream().allMatch( kr -> keys.stream().anyMatch(k -> k.getPublicKey().equals(kr.getPublicKey()))); boolean allMatch3 = keyAddresses.stream().allMatch(address -> keys.stream().anyMatch(key -> key.isMatchingKeyAddress(address))); return allMatch1 && allMatch2 && allMatch3; }
/** * Create new revision to be changed, signed sealed and then ready to approve. Created "revision" contract is a copy * of this contract, with all fields and references correctly set. After this call one need to change mutable * fields, add signing keys, seal it and then apss to Universa network for approval. * * @param keys initially added and signer keys. Role "creator" is set to addresses of these keys * @param transactional is {@link Transactional} section to create new revision with * @return new revision of this contract, identical to this one, to be modified. */ public synchronized Contract createRevisionWithAddress(Collection<?> keys, Transactional transactional) { Contract newRevision = createRevision(transactional); Set<KeyAddress> aids = new HashSet<>(); AtomicBoolean returnNull = new AtomicBoolean(false); keys.forEach(k -> { if (k instanceof AbstractKey) aids.add(((AbstractKey) k).getPublicKey().getShortAddress()); else if (k instanceof KeyAddress) aids.add((KeyAddress)k); else returnNull.set(true); }); newRevision.setCreatorKeys(aids); if (returnNull.get()) return null; return newRevision; }
@NonNull private HashMap<String, AbstractKey> prepareSigners(Binder payload) { HashMap<String, AbstractKey> sigIds = new HashMap<>(); if (signers != null && !signers.isEmpty()) { ArrayList<Binder> s = payload.set("signers", new ArrayList<>()); int i = 0; for (Binder b : signers.values()) { final String id = b.getStringOrThrow("id"); final AbstractKey key = (AbstractKey) b.get("key"); sigIds.put(id, key); Binder signerData = new Binder( "id", id, "key", key.getPublicKey().pack(), "data", b.getBinder("data") ); s.add(signerData); } } return sigIds; }
@Override public String toString() { AbstractKey k = this instanceof PrivateKey ? getPublicKey() : this; return info().toString() + ":" + info().getBase64Tag(); }
/** * Calculate keyId for a given key (should be either {@link PublicKey} or {@link PrivateKey}). the keyId is the same * for public and private key and can be used to store/access keys in Map ({@link Bytes} instances can be used as * Map keys. * <p> * Use {@link #extractKeyId(byte[])} to get a keyId from a packed extended signature, find the proper key, than * {@link #verify(PublicKey, byte[], byte[])} the data. It uses corresponding {@link PublicKey#fingerprint()}. * * @param key key to calculate Id * * @return calculated key id */ static public Bytes keyId(AbstractKey key) { if (key instanceof PrivateKey) return new Bytes(key.getPublicKey().fingerprint()); return new Bytes(key.fingerprint()); }
@Test public void findKey() throws Exception { KeyInfo i1 = new KeyInfo(KeyInfo.PRF.HMAC_SHA256, 1024, null, null); AbstractKey pk1 = i1.derivePassword("helluva"); KeyInfo i2 = new KeyInfo(KeyInfo.PRF.HMAC_SHA256, 1025, null, "the tag".getBytes()); AbstractKey pk2 = i2.derivePassword("helluva"); assertEquals(i2.getTag(), pk2.info().getTag()); KeyRing kr = new KeyRing(); SymmetricKey sk1 = new SymmetricKey(); SymmetricKey sk2 = new SymmetricKey(); AbstractKey privateKey = TestKeys.privateKey(0); AbstractKey publicKey1 =TestKeys.privateKey(1).getPublicKey(); AbstractKey publicKey2 = privateKey.getPublicKey(); kr.addKeys( sk1, sk2, privateKey, publicKey1, publicKey2, pk1, pk2 ); kr.addKeys(pk1, pk2); Binder b = kr.toBinder(); KeyRing kr2 = KeyRing.fromBinder(b); assertTrue(kr.keySet().contains(pk1)); assertTrue(kr.keySet().contains(pk2)); assertEquals(pk2, kr.findKey(i2).toArray()[0]); assertEquals(pk2, kr2.findKey(i2).toArray()[0]); final Collection<AbstractKey> keys = kr.findKey(i1); assertTrue(keys.contains(pk1)); assertTrue(keys.contains(pk1)); assertTrue(keys.contains(sk1)); assertTrue(keys.contains(sk2)); assertEquals(4, kr2.findKey(i1).size()); }
@Test public void privateKeyMustHaveInfo() throws Exception { AbstractKey prk = TestKeys.privateKey(3); AbstractKey puk = prk.getPublicKey(); KeyInfo h = prk.info(); assertEquals(KeyInfo.Algorythm.RSAPrivate, h.getAlgorythm()); assertEquals(KeyInfo.PRF.None, h.getPRF()); assertEquals(5, h.getTag().length); assertArrayEquals(puk.info().getTag(), h.getTag()); // Bytes.dump(h.pack()); }
@Test public void saveAndRestore() throws Exception { KeyRing kr = new KeyRing(); SymmetricKey sk1 = new SymmetricKey(); SymmetricKey sk2 = new SymmetricKey(); AbstractKey privateKey = TestKeys.privateKey(0); AbstractKey publicKey1 = TestKeys.privateKey(1).getPublicKey(); AbstractKey publicKey2 = privateKey.getPublicKey(); kr.addKeys( sk1, sk2, privateKey, publicKey1, publicKey2); Binder b = kr.toBinder(); KeyRing kr2 = KeyRing.fromBinder(b); for(AbstractKey k: kr2.keySet()) { assertTrue(kr2.contains(k)); assertTrue(kr.contains(k)); } assertEquals(kr, kr2); }
@Test public void matchTypeAndTag() throws Exception { // 2 different private keys AbstractKey k1 = TestKeys.privateKey(0); AbstractKey k2 = TestKeys.privateKey(1); assertTrue(k1.info().matchType(k2.info())); assertFalse(k1.info().matchTag(k2.info())); // public matches private, not vice versa AbstractKey k3 = k1.getPublicKey(); assertTrue(k1.info().matchType(k3.info())); assertFalse(k3.info().matchType(k1.info())); assertTrue(k1.info().matchTag(k3.info())); // public keys do not match each other! assertFalse(k3.info().matchType(k3.info())); assertFalse(k3.info().matchType(k2.getPublicKey().info())); // Check AES match algorythm and tag AbstractKey k4 = new SymmetricKey(); assertFalse(k2.matchType(k4)); assertFalse(k3.matchType(k4)); assertFalse(k4.matchType(k2)); assertFalse(k4.matchType(k3)); assertFalse(k4.matchTag(k2)); assertFalse(k4.matchTag(k3)); AbstractKey k5 = new SymmetricKey(); assertTrue(k4.matchType(k5)); assertTrue(k5.matchType(k4)); assertFalse(k4.matchTag(k5)); k4.setTag("Hello"); k5.setTag("Hello"); }