public XMSSNode getTailNode() { return tailNode.clone(); } }
.withTreeAddress(hashTreeAddress.getTreeAddress()).withTreeIndex(indexLeaf) .withKeyAndMask(hashTreeAddress.getKeyAndMask()).build(); while (!stack.isEmpty() && stack.peek().getHeight() == node.getHeight()) int indexOnHeight = indexLeaf / (1 << node.getHeight()); if (indexOnHeight == 1) authenticationPath.add(node.clone()); if (indexOnHeight == 3 && node.getHeight() < (treeHeight - k)) treeHashInstances.get(node.getHeight()).setNode(node.clone()); if (indexOnHeight >= 3 && (indexOnHeight & 1) == 1 && node.getHeight() >= (treeHeight - k) && node.getHeight() <= (treeHeight - 2)) if (retain.get(node.getHeight()) == null) queue.add(node.clone()); retain.put(node.getHeight(), queue); retain.get(node.getHeight()).add(node.clone()); .withKeyAndMask(hashTreeAddress.getKeyAndMask()).build(); node = XMSSNodeUtil.randomizeHash(wotsPlus, stack.pop(), node, hashTreeAddress); node = new XMSSNode(node.getHeight() + 1, node.getValue()); hashTreeAddress = (HashTreeAddress)new HashTreeAddress.Builder() .withLayerAddress(hashTreeAddress.getLayerAddress())
public byte[] toByteArray() { /* signature || authentication path */ int n = params.getDigestSize(); int signatureSize = params.getWOTSPlus().getParams().getLen() * n; int authPathSize = params.getHeight() * n; int totalSize = signatureSize + authPathSize; byte[] out = new byte[totalSize]; int position = 0; /* copy signature */ byte[][] signature = this.wotsPlusSignature.toByteArray(); for (int i = 0; i < signature.length; i++) { XMSSUtil.copyBytesAtOffset(out, signature[i], position); position += n; } /* copy authentication path */ for (int i = 0; i < authPath.size(); i++) { byte[] value = authPath.get(i).getValue(); XMSSUtil.copyBytesAtOffset(out, value, position); position += n; } return out; }
for (int i = 0; i < height; i++) nodeList.add(new XMSSNode(i, XMSSUtil.extractBytesAtOffset(reducedSignature, position, n))); position += n;
void setNode(XMSSNode node) { tailNode = node; height = node.getHeight(); if (height == initialHeight) { finished = true; } }
/** * Generate a new XMSS private key / public key pair. */ public AsymmetricCipherKeyPair generateKeyPair() { /* generate private key */ XMSSPrivateKeyParameters privateKey = generatePrivateKey(params, prng); XMSSNode root = privateKey.getBDSState().getRoot(); privateKey = new XMSSPrivateKeyParameters.Builder(params) .withSecretKeySeed(privateKey.getSecretKeySeed()).withSecretKeyPRF(privateKey.getSecretKeyPRF()) .withPublicSeed(privateKey.getPublicSeed()).withRoot(root.getValue()) .withBDSState(privateKey.getBDSState()).build(); XMSSPublicKeyParameters publicKey = new XMSSPublicKeyParameters.Builder(params).withRoot(root.getValue()) .withPublicSeed(privateKey.getPublicSeed()).build(); return new AsymmetricCipherKeyPair(publicKey, privateKey); }
for (int i = 0; i < publicKeyBytes.length; i++) publicKeyNodes[i] = new XMSSNode(0, publicKeyBytes[i]);
XMSSNode node = XMSSNodeUtil.lTree(wotsPlus, wotsPlusPublicKey, lTreeAddress); while (!stack.isEmpty() && stack.peek().getHeight() == node.getHeight() && stack.peek().getHeight() != initialHeight) .withKeyAndMask(hashTreeAddress.getKeyAndMask()).build(); node = XMSSNodeUtil.randomizeHash(wotsPlus, stack.pop(), node, hashTreeAddress); node = new XMSSNode(node.getHeight() + 1, node.getValue()); hashTreeAddress = (HashTreeAddress)new HashTreeAddress.Builder() .withLayerAddress(hashTreeAddress.getLayerAddress()) if (tailNode.getHeight() == node.getHeight()) .withKeyAndMask(hashTreeAddress.getKeyAndMask()).build(); node = XMSSNodeUtil.randomizeHash(wotsPlus, tailNode, node, hashTreeAddress); node = new XMSSNode(tailNode.getHeight() + 1, node.getValue()); tailNode = node; hashTreeAddress = (HashTreeAddress)new HashTreeAddress.Builder() if (tailNode.getHeight() == initialHeight) height = node.getHeight(); nextIndex++;
byte[] value = getAuthPath().get(i).getValue(); XMSSUtil.copyBytesAtOffset(out, value, position); position += n;
protected XMSSNode getRoot() { return root.clone(); }
.withKeyAndMask(hashTreeAddress.getKeyAndMask()).build(); node[1] = XMSSNodeUtil.randomizeHash(wotsPlus, node[0], signature.getAuthPath().get(k), hashTreeAddress); node[1] = new XMSSNode(node[1].getHeight() + 1, node[1].getValue()); .withKeyAndMask(hashTreeAddress.getKeyAndMask()).build(); node[1] = XMSSNodeUtil.randomizeHash(wotsPlus, signature.getAuthPath().get(k), node[0], hashTreeAddress); node[1] = new XMSSNode(node[1].getHeight() + 1, node[1].getValue());
protected List<XMSSNode> getAuthenticationPath() { List<XMSSNode> authenticationPath = new ArrayList<XMSSNode>(); for (XMSSNode node : this.authenticationPath) { authenticationPath.add(node.clone()); } return authenticationPath; }
/** * Generate a new XMSSMT private key / public key pair. */ public AsymmetricCipherKeyPair generateKeyPair() { XMSSMTPrivateKeyParameters privateKey; XMSSMTPublicKeyParameters publicKey; /* generate XMSSMT private key */ privateKey = generatePrivateKey(new XMSSMTPrivateKeyParameters.Builder(params).build().getBDSState()); /* import to xmss */ xmssParams.getWOTSPlus().importKeys(new byte[params.getDigestSize()], privateKey.getPublicSeed()); /* get root */ int rootLayerIndex = params.getLayers() - 1; OTSHashAddress otsHashAddress = (OTSHashAddress)new OTSHashAddress.Builder().withLayerAddress(rootLayerIndex) .build(); /* store BDS instance of root xmss instance */ BDS bdsRoot = new BDS(xmssParams, privateKey.getPublicSeed(), privateKey.getSecretKeySeed(), otsHashAddress); XMSSNode root = bdsRoot.getRoot(); privateKey.getBDSState().put(rootLayerIndex, bdsRoot); /* set XMSS^MT root / create public key */ privateKey = new XMSSMTPrivateKeyParameters.Builder(params).withSecretKeySeed(privateKey.getSecretKeySeed()) .withSecretKeyPRF(privateKey.getSecretKeyPRF()).withPublicSeed(privateKey.getPublicSeed()) .withRoot(root.getValue()).withBDSState(privateKey.getBDSState()).build(); publicKey = new XMSSMTPublicKeyParameters.Builder(params).withRoot(root.getValue()) .withPublicSeed(privateKey.getPublicSeed()).build(); return new AsymmetricCipherKeyPair(publicKey, privateKey); }
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()); }
wotsPlusSignature = wotsSign(root.getValue(), otsHashAddress);