/** * Constructs a new WOTS+ one-time signature system based on the given WOTS+ * parameters. * * @param params Parameters for WOTSPlus object. */ protected WOTSPlus(WOTSPlusParameters params) { super(); if (params == null) { throw new NullPointerException("params == null"); } this.params = params; int n = params.getDigestSize(); khf = new KeyedHashFunctions(params.getDigest(), n); secretKeySeed = new byte[n]; publicSeed = new byte[n]; }
/** * Derive private key at index from secret key seed. * * @param index Index. * @return Private key at index. */ private byte[] expandSecretKeySeed(int index) { if (index < 0 || index >= params.getLen()) { throw new IllegalArgumentException("index out of bounds"); } return khf.PRF(secretKeySeed, XMSSUtil.toBytesBigEndian(index, 32)); }
protected byte[] HMsg(byte[] key, byte[] in) { if (key.length != (3 * digestSize)) { throw new IllegalArgumentException("wrong key length"); } return coreDigest(2, key, in); }
.withOTSAddress(otsHashAddress.getOTSAddress()).withChainAddress(otsHashAddress.getChainAddress()) .withHashAddress(startIndex + steps - 1).withKeyAndMask(0).build(); byte[] key = khf.PRF(publicSeed, otsHashAddress.toByteArray()); otsHashAddress = (OTSHashAddress)new OTSHashAddress.Builder() .withLayerAddress(otsHashAddress.getLayerAddress()).withTreeAddress(otsHashAddress.getTreeAddress()) .withOTSAddress(otsHashAddress.getOTSAddress()).withChainAddress(otsHashAddress.getChainAddress()) .withHashAddress(otsHashAddress.getHashAddress()).withKeyAndMask(1).build(); byte[] bitmask = khf.PRF(publicSeed, otsHashAddress.toByteArray()); byte[] tmpMasked = new byte[n]; for (int i = 0; i < n; i++) tmp = khf.F(key, tmpMasked); return tmp;
byte[] key = wotsPlus.getKhf().PRF(publicSeed, address.toByteArray()); byte[] bitmask0 = wotsPlus.getKhf().PRF(publicSeed, address.toByteArray()); byte[] bitmask1 = wotsPlus.getKhf().PRF(publicSeed, address.toByteArray()); int n = wotsPlus.getParams().getDigestSize(); byte[] tmpMask = new byte[2 * n]; byte[] out = wotsPlus.getKhf().H(key, tmpMask); return new XMSSNode(left.getHeight(), out);
byte[] messageDigest = wotsPlus.getKhf().HMsg(concatenated, message);
byte[] random = wotsPlus.getKhf().PRF(privateKey.getSecretKeyPRF(), XMSSUtil.toBytesBigEndian(globalIndex, 32)); byte[] concatenated = Arrays.concatenate(random, privateKey.getRoot(), XMSSUtil.toBytesBigEndian(globalIndex, params.getDigestSize())); byte[] messageDigest = wotsPlus.getKhf().HMsg(concatenated, message);
public boolean verifySignature(byte[] message, byte[] signature) { /* parse signature and public key */ XMSSSignature sig = new XMSSSignature.Builder(params).withSignature(signature).build(); /* generate public key */ int index = sig.getIndex(); /* reinitialize WOTS+ object */ params.getWOTSPlus().importKeys(new byte[params.getDigestSize()], publicKey.getPublicSeed()); /* create message digest */ byte[] concatenated = Arrays.concatenate(sig.getRandom(), publicKey.getRoot(), XMSSUtil.toBytesBigEndian(index, params.getDigestSize())); byte[] messageDigest = khf.HMsg(concatenated, message); int xmssHeight = params.getHeight(); int indexLeaf = XMSSUtil.getLeafIndex(index, xmssHeight); /* get root from signature */ OTSHashAddress otsHashAddress = (OTSHashAddress)new OTSHashAddress.Builder().withOTSAddress(index).build(); XMSSNode rootNodeFromSignature = XMSSVerifierUtil.getRootNodeFromSignature(params.getWOTSPlus(), xmssHeight, messageDigest, sig, otsHashAddress, indexLeaf); return Arrays.constantTimeAreEqual(rootNodeFromSignature.getValue(), publicKey.getRoot()); }
protected byte[] F(byte[] key, byte[] in) { if (key.length != digestSize) { throw new IllegalArgumentException("wrong key length"); } if (in.length != digestSize) { throw new IllegalArgumentException("wrong in length"); } return coreDigest(0, key, in); }
/** * Derive WOTS+ secret key for specific index as in XMSS ref impl Andreas * Huelsing. * * @param otsHashAddress * @return WOTS+ secret key at index. */ protected byte[] getWOTSPlusSecretKey(byte[] secretKeySeed, OTSHashAddress otsHashAddress) { otsHashAddress = (OTSHashAddress)new OTSHashAddress.Builder() .withLayerAddress(otsHashAddress.getLayerAddress()).withTreeAddress(otsHashAddress.getTreeAddress()) .withOTSAddress(otsHashAddress.getOTSAddress()).build(); return khf.PRF(secretKeySeed, otsHashAddress.toByteArray()); }
protected byte[] H(byte[] key, byte[] in) { if (key.length != digestSize) { throw new IllegalArgumentException("wrong key length"); } if (in.length != (2 * digestSize)) { throw new IllegalArgumentException("wrong in length"); } return coreDigest(1, key, in); }
protected byte[] PRF(byte[] key, byte[] address) { if (key.length != digestSize) { throw new IllegalArgumentException("wrong key length"); } if (address.length != 32) { throw new IllegalArgumentException("wrong address length"); } return coreDigest(3, key, address); } }