openhub.net
Black Duck Software, Inc.
Open Hub
Follow @
OH
Sign In
Join Now
Projects
People
Organizations
Tools
Blog
BDSA
Projects
People
Projects
Organizations
B
bouncy Castle Java
Settings
1
I Use This!
×
Login Required
Log in to Open Hub
Remember Me
Very High Activity
Commits
: Listings
Analyzed
about 11 hours
ago. based on code collected
1 day
ago.
Nov 07, 2025 — Nov 07, 2026
Showing page 21 of 806
Search / Filter on:
Commit Message
Contributor
Files Modified
Lines Added
Lines Removed
Code Location
Date
Let the OTS hash address travel through this package as its 32-byte encoding, the way the L-tree and the hash tree addresses already do. The one-time keys of a tree differ in one word of that encoding, so a walk that holds the encoding steps that word rather than building an address and encoding it again per leaf: BDS.initialize and BDSTreeHash.update write the OTS address word into one of their own, WOTSPlus.getWOTSPlusSecretKey, getPublicKey, sign and getPublicKeyFromSignature take that encoding where they took an address, and XMSSNodeUtil.withOTSAddress - which existed to rebuild one per leaf out of the fields of another - goes with them. What such a walk still needs off the address it was handed is the layer address and the tree address, to name the L-tree and the hash tree addresses of the same tree, and it reads those back out of the encoding through XMSSAddress.layerAddressOf and treeAddressOf: RFC 8391 sec. 2.5 gives every address type the same first four words, so the two readers answer whichever type produced the encoding, and AddressTests pins that layout independently of anything here. OTSHashAddress.Builder stays as what produces an encoding at the ten places a walk starts, which is the role LTreeAddress.Builder and HashTreeAddress.Builder have held since their own walks were changed this way. Which side may write is the part worth stating rather than leaving to be inferred: WOTSPlus writes named words into the caller's encoding, as lTree and randomizeHash do, while BDS, BDSTreeHash and XMSSVerifierUtil read the caller's and never write it - the two walks in BDS step an Arrays.clone of it. That copy is load-bearing in initialize, because XMSSEngine.generateMTSignature builds a layer-0 state and then signs with the same address, and aliasing would hand the signature an OTS address word left at 2^h - 1; in nextAuthenticationPath it is the same contract rather than a live hazard, since nothing reached today reads back the OTS address word of what it passed, and the javadoc there says so rather than implying more. The bytes are unchanged and are pinned as such: XMSSPromotionCompatibilityTest compares keys, signatures and cross-verification against the deprecated org.bouncycastle.pqc.crypto.xmss copy over six parameter sets and every index of a key, and passes, as do crypto.signers.xmss.AllTests at 90, the provider's XMSSTest at 31 and XMSSMTTest at 27, pqc.crypto.test.AllTests at 136 and core's checkstyleMain. What it saves is measured over com.sun.management.ThreadMXBean.getThreadAllocatedBytes and reproduces to the byte: an h = 10 SHA-256 key generation falls from 10957032 to 10760520 bytes and an XMSS^MT h = 20 d = 2 first signature from 21966224 to 21572960, both 1.79%. The keygen figure is 1024 x 192 less 96 exactly - a 48-byte Builder, a 48-byte address and two 48-byte byte[32] per leaf, against the one clone initialize now makes and the one encoding taken at the entry site - so four allocations a leaf, 4096 of them. That the tests reach the new stepping sites is measured the same way as before, in a shadow class tree put ahead of core's: writing indexLeaf + 1 rather than indexLeaf in initialize fails all six compatibility cases and nextIndex + 1 in BDSTreeHash.update fails one of them, while aliasing instead of cloning in initialize fails three, every one of them XMSS^MT, and aliasing in nextAuthenticationPath fails none. The three clearing writes the previous commit kept against a mutation saying they were not load-bearing are load-bearing now: dropping them fails five of the six cases, because one encoding serves a whole leaf walk and getPublicKey leaves the last chain's chain address, hash address and key-and-mask in it for the next leaf's one-time key to be derived from.
gefeili
More...
2 months ago
Stop WOTSPlus.getWOTSPlusSecretKey building a second OTSHashAddress to zero three words of one. The address this derivation is the PRF of is the caller's with its chain address, hash address and key-and-mask cleared, and it was reaching that by building a fresh address out of the three fields that survive - a Builder and an OTSHashAddress per one-time key, so 1024 of each in an h = 10 key generation - and then encoding it. The caller's own encoding differs from that one in exactly the three words being cleared, all of which this package already names for the loops that step them, so the zeros go into it directly: one byte[32] where there were a Builder, an address and a byte[32], with the layout left where toByteArray() keeps it rather than spelled out a second time. The bytes are the same by construction - the rebuild copied the layer address, the tree address and the OTS address across, both addresses carry the OTS type word, and the only words a Builder left at zero are the three now being cleared - and they are pinned as such rather than assumed: XMSSPromotionCompatibilityTest compares keys, signatures and cross-verification against the deprecated org.bouncycastle.pqc.crypto.xmss copy over six parameter sets and every index of a key, and passes, as do crypto.signers.xmss.AllTests at 90, the provider's XMSSTest at 31 and XMSSMTTest at 27, pqc.crypto.test.AllTests at 136 and core's checkstyleMain. What it saves is measured over com.sun.management.ThreadMXBean.getThreadAllocatedBytes and is reproducible to the byte across runs: an h = 10 SHA-256 key generation falls from 11055336 to 10957032 bytes, and the 98304 is 1024 x 96 exactly - one 48-byte Builder and one 48-byte address per leaf - while an XMSS^MT h = 20 d = 2 first signature falls from 22166336 to 21966224. That the tests reach this encoding at all is measured too, in a shadow class tree put ahead of core's: writing 1 rather than 0 into the key-and-mask word fails five of the six compatibility cases, each of them on differing public key encodings. The clearing is kept even though a second mutation says it is not load-bearing anywhere exercised - dropping all three writes leaves both the six compatibility cases and all 90 of AllTests green, so every call site reached today already hands in an address carrying zeros there - because XMSSNodeUtil.withOTSAddress carries those three fields over from whatever address a leaf walk was seeded with, and a caller seeding one with a stepped address would otherwise derive a different one-time key in silence. Three int writes is what that costs.
gefeili
More...
2 months ago
Compare an XMSS^MT raw private key encoding against the deprecated copy, which nothing in this tree did.
gefeili
More...
2 months ago
Refuse an index the private key index field cannot hold rather than writing it narrowed. The raw layout writes the XMSS^MT index in ceil(h / 8) bytes, and the largest index a key can hold is 2^h - the position it stops at when its last one-time key is spent, one past its final leaf, which isStoredIndexValid admits, which BDS.validate admits and which the state serialization carries - so at every total height that is a multiple of eight the field is one bit short of the one index it most has to be able to write.
gefeili
More...
2 months ago
Compare the traversal state rather than the whole key at the end of a private key's equals(), and the two secret seeds in the gate in front of it. A key's encoding is index || secretKeySeed || secretKeyPRF || publicSeed || root || traversal state. The gate this method grew last already answered on the index, the public seed and the root, so what the encoding added over it was the two secret seeds and the state; comparing those seeds above and the state alone below decides on the same eight things - those six plus the tree digest and the usages remaining - in the same constant time, and takes the encoding of a whole key out of the method. At an h=10 SHA-256 XMSS key that encoding is 1138 bytes of which the state is 1006, and for XMSS^MT h=20 d=2 1153 of which 1022, so what goes is the four n-byte fields being written into an array in order to be compared as part of it, on both keys, every call.
gefeili
More...
2 months ago
Write the private key layout once rather than four times. Both families store a private key as index || secretKeySeed || secretKeyPRF || publicSeed || root || BDS traversal state, and both had that written out by hand on both sides - the decoding constructor and toByteArray() - so one layout lived in four places and had to be hand edited in lockstep whenever it moved. That is the position XMSSPublicKeyCodec was extracted from for the public halves, and its own note says so; XMSSPrivateKeyCodec is the same thing for the private ones. The two key classes lose 112 lines between them for 26, and their Pack import with them: what is left in each is which fields a key holds, not where those fields sit in an array.
gefeili
More...
2 months ago
Build the two private key ASN.1 structures out of the key's own fields instead of out of its encoding. Both were written the same way: encode the whole key - the four n-byte fields and the BDS traversal state, with the SHA-256 checksum over it - and then take that array apart again at computed offsets to recover the fields the key already exposes through getIndex(), getSecretKeySeed(), getSecretKeyPRF(), getPublicSeed() and getRoot(). Only the state's own encoding is what the structure needs, and only that is built now. At an h=10 SHA-256 XMSS key the encoding is 1138 bytes of which the state is 1006, so what goes is a second 1138-byte array and the six copies that filled and emptied it, once per private key export - and a stateful scheme exports a key about as often as it signs with one.
gefeili
More...
2 months ago
Stop BCXMSSPrivateKey and BCXMSSMTPrivateKey re-encoding both keys to answer every equals(). Producing a private key encoding means writing the whole BDS traversal state - the authentication path, the retain queues, the stack, every tree hash and every kept node, with a SHA-256 checksum over the result, and for XMSS^MT that once per layer - and the method did it on both operands before looking at anything, so two keys that differ in their index cost two of those to say so.
gefeili
More...
2 months ago
Put what a registered parameter set identifier is in one place instead of three. WOTSPlusOid, DefaultXMSSOid and DefaultXMSSMTOid differ in the table they hold and in what that table is keyed by; everything else about them was the same two fields, the same constructor, the same getOid() and the same toString(), written out once each. XMSSOid, which they all named and which was an interface declaring those two accessors and supplying neither, is the abstract class that carries them now.
gefeili
More...
2 months ago
Let a BDS state map be copied before its WOTS+ digest is named, which the public copy constructor could not do: a state's WOTS+ parameters are not part of what it is serialized as, so a state map that has just come back from getBDSStateMapFromEncoding carries none, and BDS's copy constructor read them off the state it was copying without asking. new BDSStateMap(decoded, maxIndex) was therefore a NullPointerException, and so was the public builder, which copies what it is handed - so withBDSState(decoded).build() threw out of a private constructor two classes away. Nothing in the type system said withWOTSDigest() had to be called first; the one caller in this tree calls it first because the comment beside it says to.
gefeili
More...
2 months ago
An HSS private key repositioned within a tree it already holds now keeps that tree rather than regenerating one identical to it, an LMS Merkle tree being a function of the key identifier, the master secret and the parameter sets and not of the one-time index, so both the root of any hierarchy and any lower level whose parent has not moved share the node cache and public key of the key they replace while still encoding byte for byte as regeneration did, relates to github #2414.
David Hook
More...
2 months ago
KeyPairGenerator.initialize(AlgorithmParameterSpec, SecureRandom) now reports a spec it will not take as the InvalidAlgorithmParameterException it declares across all the services the two providers register rather than only 44 of them, the twenty-three PQC generators that resolve a parameter set by name no longer case-folding the null a spec with no getName() yields and so reaching their own name check, the two composite generators refusing a non-null spec with the declared exception rather than an IllegalArgumentException, and the RSA generator translating the values its lightweight parameters refuse the way the int overload's are.
David Hook
More...
2 months ago
Hold the state map's monitor across the whole of BDSStateMap.validateIndex rather than once per layer. It walked the layers calling get(layer), which synchronizes for the one read and lets go again, so the walk was a sequence of locks and not a lock: a signature landing between two of them leaves it comparing layers from before that signature against layers from after it, and what it then reports - or fails to report - is about a state map no instant produced. The other two walks over this map, validate(XMSSMTParameters) and getStateMap(), already take the monitor once and read bdsState directly inside it, and the copy constructor's javadoc gives the reason in full; this is the third and it had been left out.
gefeili
More...
2 months ago
Have BDS.getRetain() hand out the retain queues rather than the map that holds them. It copied with putAll, which copies the map and leaves every value pointing at the LinkedList the live traversal state reads from - so a caller that took a node out of one to look at it took it out of the key. The three accessors beside it were given a copy of their own depth when the state's collections were last looked at, and the note left above them says getRetain() already did the same; it did not, and it is the one where the difference is a level down from what the method returns. It goes through cloneRetain(), which is what the constructors take a state apart with, so the two now say the same thing once.
gefeili
More...
2 months ago
Every key pair generator that will not take the key size handed to KeyPairGenerator.initialize(int, SecureRandom) now reports it as the InvalidParameterException the JCA specifies rather than a bare IllegalArgumentException, so a caller catching the documented type reads a refusal rather than an escaping exception, covering the thirty PQC generators whose parameter set cannot be named by a key size at all and RSA, whose refusal comes from the lightweight RSAKeyGenerationParameters and is now translated through a new SecurityExceptions.invalidParameterException keeping the message and chaining the original as the cause, with InvalidParameterException extending IllegalArgumentException so existing catches still match.
David Hook
More...
2 months ago
Delete the WOTS+ instance XMSS^MT key generation built and threw away. It was constructed, given an all-zero secret key seed and the key's public seed, and then dropped on the same line - never assigned, never read - so the only way it could have mattered is by leaving something behind or by refusing what it was given, and it does neither. importKeys copies its two arguments into arrays the WOTS+ constructor has already allocated, deliberately and with a comment saying why, so nothing it touches outlives the temporary; and it cannot throw here, since both arrays are exactly the tree digest size the parameters name. The root the key pair is built around comes from the BDS three lines below, which constructs its own WOTS+ from the same parameters.
gefeili
More...
2 months ago
TimeStampToken now reports a malformed TSTInfo, and a token signed by other than one signer, as the TSPException its constructor declares rather than letting an unchecked exception out through the TimeStampResponse byte[] and InputStream paths, and asn1.tsp.TSTInfo requires the five to ten elements RFC 3161 sec. 2.4.2 gives the type so a short sequence is refused rather than running its enumeration out, relates to github #2415.
David Hook
More...
2 months ago
The high-level OpenPGP message reader now updates and verifies only those prefixed (non-one-pass) signatures whose PGPSignature was successfully initialised, so a message whose signer certificate was not supplied returns its plaintext with the signature unreported rather than throwing a NullPointerException out of read(), and the one-pass path no longer dereferences a null issuer key, relates to github #2417.
David Hook
More...
2 months ago
Merge branch 'main' into xmss-promote-crypto-signers-pick
gefeili
More...
2 months ago
Stop BDS.validate cloning a node's whole value to look at its length, which it was doing for every node of every state validated - the root, each node of the authentication path, of the retain queues, of the stack, each tree hash's tail and each kept node. It asks XMSSNode for the answer now, through a hasValueLength(n) that reports rather than dereferences, because the check it is making has a null half that has to survive the change: a BDS can arrive by Java deserialization - the pre-BDSStateCodec form is still read, XMSSUtil.deserialize behind XMSSEngine.importBDSState and importBDSStateMap - and deserialization writes an object's fields directly, so it hands back an XMSSNode holding no value at all where none of this package's five calls to that constructor can, every one of them passing an array it has just built. getValueLength() would not answer for such a node, and BDS.readObject says in as many words that it does not walk into the nodes its collections hold because validate() is what checks them. So the length question moves onto the node whole rather than the length alone being fetched.
gefeili
More...
2 months ago
Delete WOTSPlusPublicKeyParameters.toByteArray(), which no caller in the main tree ever had - all six of its references are in WOTSPlusTests - leaving toNodes() as the only way the key's len n-byte blocks leave the class, and the class with no imports again. The method deep-copied the array the constructor takes over, and nothing observed that copy: making it shallow left all 85 of crypto.signers.xmss.AllTests green. What the tests want it for is two snapshots - compress a key and compare the key against what it was, recover a key from a signature and then flip the signature's bytes - and a snapshot that aliases the key asserts nothing at all, so the copy moves into the test as blocksOf(), which walks toNodes() and writes each node's value into a fresh block through encodeTo() rather than reading it through the copy getValue() makes. That is deliberate: it keeps the snapshot a copy whatever getValue() is later decided to hand back, so neither test can quietly become an assertion about nothing. The other four references compare two keys and become blocksOf() on each side, keeping XMSSUtil.areEqual and the note saying why it is not org.bouncycastle.util.Arrays.areEqual - which has no byte[][] overload, so it would bind to areEqual(Object[], Object[]) and compare the rows by reference. AllTests stays at 85: blocksOf is a private helper, not a case. The results are unchanged and are pinned as such rather than assumed: XMSSPromotionCompatibilityTest compares keys, signatures and cross-verification against the deprecated org.bouncycastle.pqc.crypto.xmss copy over six parameter sets and every index of a key, and passes, as do crypto.signers.xmss.AllTests at 85, the provider's XMSSTest at 29 and XMSSMTTest at 25, pqc.crypto.test.AllTests at 136 and core's checkstyleMain. Three mutations confirm the rewritten assertions still reach what they describe, each built into a shadow class tree put ahead of core's: maskInto disturbing the node value it has just read fails testCompressingAPublicKeyDoesNotDisturbIt on "compressing a public key changed the key"; chain() handing its starting value back at zero steps fails testChainedBlocksAreArraysOfTheirOwn on "two blocks of one signature are the same array"; and getPublicKeyFromSignature taking the signature's blocks as the recovered key's fails the same test on "a recovered public key shares storage with the signature it came from", which is the one that would pass if blocksOf were handing back aliases rather than copies.
gefeili
More...
2 months ago
Take the two cloneArray helpers out and let their 33 call sites clone with org.bouncycastle.util.Arrays directly - the byte[] one, the byte[][] one, and the public XMSSEngine.cloneArray bridge that existed only so the four crypto.params key classes could reach the first, XMSSUtil being package-private in another package. Each was Arrays.clone with a null check in front of it and neither check was doing work. The byte[][] one, hasNullPointer, had a single caller - WOTSPlusPublicKeyParameters.toByteArray(), over the array that class's constructor took over, which both of the two builders reaching it allocate as new byte[len][] and fill at every index with what chain() returns, the class being package-private and final so that is a list rather than a guess - and so, like the validateShape removed two commits ago, it could only compare a value with itself. The byte[] one threw NullPointerException("in == null") where Arrays.clone answers null, and the one place that difference is observable is the sixteen builder setters, where it rejected one spelling of absent while the builder went on accepting the other. Measured against HEAD's own classes in a shadow tree: XMSSPublicKeyParameters.Builder.withRoot(null) and .withPublicKey(null) each threw, while build() with neither called returned a key with an all-zero root; XMSSPrivateKeyParameters.Builder.withPrivateKey(null) and .withRoot(null) each threw, while build() with neither called reported IllegalStateException("publicSeed or secretKeySeed is null"). With the check gone each of those four lands exactly where its no-setter twin lands - the same zero root, the same IllegalStateException - so nothing is reachable now that a caller could not already reach by leaving the setter out, and that is why no check is written back at any of the 33 sites. The remaining twelve params-side sites are getters and cannot see a null at all: every field they copy is one the constructor pinned, through validateOrAllocate on the set branch or through copyOfRange on the import branch. Arrays.clone(byte[][]) clones each row, so toByteArray() still deep-copies - that is read from its source rather than measured, and what a measurement says instead is that nothing observes it: making that clone shallow leaves all 85 of crypto.signers.xmss.AllTests green, the method having no caller in the main tree at all and six in WOTSPlusTests. XMSSEngine keeps validateOrAllocate, which those same four key classes call twelve times over, alongside the fourteen other public statics they take from it. The results are unchanged and are pinned as such rather than assumed: XMSSPromotionCompatibilityTest compares keys, signatures and cross-verification against the deprecated org.bouncycastle.pqc.crypto.xmss copy over six parameter sets and every index of a key, and passes, as do crypto.signers.xmss.AllTests at 85, the provider's XMSSTest at 29 and XMSSMTTest at 25, pqc.crypto.test.AllTests at 136 and core's checkstyleMain.
gefeili
More...
2 months ago
The PKCS#12 key stores now report a certificate whose public key cannot be resolved, and a zero-length certificate chain, as the KeyStoreException engineSetKeyEntry and engineSetCertificateEntry declare, and check both ahead of the assignments so a refused entry is not left behind in the store, relates to github #2419.
David Hook
More...
2 months ago
BIP340Signer can now be initialised from an AsymmetricCipherKeyPair, taking the public key from the caller rather than deriving it with a d'*G multiplication, which roughly halves the cost of producing a signature, and derives that point once per init() rather than on every generateSignature() call, relates to github #2420.
David Hook
More...
2 months ago
Replace the WOTSPlusSignature carrier with the byte[][] it held, which after the last two commits is all it was: the constructor took the array over rather than copying it in, and the shape check it applied went with validateShape, so what remained was a field, a getBlock(i) that is signature[i], a five-line encodeTo with one caller, and a deep-copying toByteArray() whose only caller anywhere is a test asserting the block count - now signature.length. WOTSPlus.sign and XMSSEngine.wotsSign return the array, getPublicKeyFromSignature and XMSSReducedSignature.Builder.withWOTSPlusSignature take one, and XMSSReducedSignature holds one; all of those are package-private, as are XMSSReducedSignature and the two signature classes extending it, so the array does not leave the package, and the two notes on the deleted accessors move to where the blocks are now read - getPublicKeyFromSignature's javadoc says it reads them and never writes them, getWOTSPlusSignature's says the same of its one caller. The encoding changes shape without changing bytes: what was WOTSPlusSignature.encodeTo is now a loop inline in XMSSReducedSignature.encodeTo, beside the authentication path loop it mirrors, copying n bytes per block and advancing n rather than copying signature[i].length per block and letting the caller advance by len * n afterwards. Those agree because every block is exactly n and there are exactly len of them, from the same three construction sites as before - and the builder that could supply a fourth is package-private with two callers, both wotsSign - while where they would not agree the old pair wrote a short encoding in silence and the new loop throws, which is the better of the two answers to a signature that cannot exist. WOTSPlusPublicKeyParameters stays as it is: toNodes() is a thing to do with the blocks rather than a way of reaching them, so that class still earns its name. Nothing outside these five files named the type. The results are unchanged and are pinned as such rather than assumed: XMSSPromotionCompatibilityTest compares keys, signatures and cross-verification against the deprecated org.bouncycastle.pqc.crypto.xmss copy over six parameter sets and every index of a key, and passes, as do crypto.signers.xmss.AllTests at 85, the provider's XMSSTest and XMSSMTTest, pqc.crypto.test.AllTests and core's checkstyleMain. That the inlined loop is what produces every encoding is measured rather than assumed too: copying n - 1 bytes per block instead of n fails nine of the 85 in AllTests, all six of the compatibility oracle - each of them on differing signature bytes - 17 of the 29 in XMSSTest and 15 of the 25 in XMSSMTTest.
gefeili
More...
2 months ago
Stop WOTSPlusParameters holding the WOTS+ parameter set identifier its constructor looks up, which nothing has ever read - no caller of getOid() exists in this package, in prov, or in either module's tests - and say at the lookup what it is still there for, because with the field gone the call reads like a leftover. It is not one: whether the (digest name, n, w, len) combination has an entry is the only thing that refuses a security parameter no XMSS parameter set defines. Both constructors that take one - XMSSParameters(height, tree digest OID, n) and XMSSMTParameters(height, layers, tree digest OID, n) - are public and pass n through unexamined, len1, len2 and len are computed from whatever it is, and the XMSS parameter set lookup that follows answers an unregistered combination with 0 rather than a complaint, so nothing downstream would object either: with this lookup taken out, SHA-256 at n = 1, 17 or 64 all construct. ParameterBoundsTests now walks nine such sizes through both classes and asserts the message, alongside the two SHA-256 sets that must keep working, being RFC 8391 XMSS-SHA2_*_256 at n = 32 and SP 800-208 XMSS-SHA2_*_192 at n = 24. Zero and below are not among them, and finding out why is what the test cost: they are not sizes at all to these constructors, whose n > 0 asks for an explicit one and whose anything else means take the digest's own, so a first draft listing zero failed against the unmutated tree. Taking the check out fails exactly this test and nothing else, on the first size it is handed. crypto.signers.xmss.AllTests goes 84 to 85, and it, XMSSPromotionCompatibilityTest against the deprecated org.bouncycastle.pqc.crypto.xmss copy, the provider's XMSSTest and XMSSMTTest, pqc.crypto.test.AllTests and core's checkstyleMain all pass.
gefeili
More...
2 months ago
Drop the shape check a WOTS+ public key and signature were each built through, and with it the WOTSPlusParameters argument both constructors carried only to reach it - so validateShape goes, and the two XMSSEngine.newWOTSPlusParameters(params) calls that existed only to supply it go with it. The check measured an array against the len and n of a parameters object, and every one of the five call sites derives the array's shape from that same object: WOTSPlus.sign, getPublicKey and getPublicKeyFromSignature each allocate new byte[params.getLen()][] and fill every entry with what chain() returns, which is a byte[params.getTreeDigestSize()], from the WOTSPlus instance's own params; XMSSReducedSignature's two branches read their len and n from an XMSSParameters, whose len is what new WOTSPlusParameters(its tree digest OID, its tree digest size).getLen() answers, and built the check's parameters from that same pair. So all four of its rejections - null array, null element, wrong element count, wrong element length - could only compare a value with itself, and the classes being package-private and final is what makes that a list rather than a guess. Nothing that arrives from outside loses a check: the one place untrusted bytes reach either class is the reduced signature decode, which rejects an encoding of the wrong total length before it slices anything, and it is that slicing - copyOfRange of exactly n at each of len positions - that fixes the shape the check was re-measuring afterwards. Both constructors' javadoc now says this, so the next reader has the argument rather than the appearance of a missing guard, and chain()'s comment stops saying the two carriers clone what it returns, which stopped being true one commit ago. The test that was the check's only reader goes too, taking crypto.signers.xmss.AllTests from 85 to 84. The results are unchanged and are pinned as such rather than assumed: XMSSPromotionCompatibilityTest compares keys, signatures and cross-verification against the deprecated org.bouncycastle.pqc.crypto.xmss copy over six parameter sets and every index of a key, and passes, as do the provider's XMSSTest and XMSSMTTest, pqc.crypto.test.AllTests and core's checkstyleMain. No verify-path saving is claimed for the two removed parameter constructions - one per reduced signature decoded, so one per XMSS verification and one per layer of an XMSS^MT one. With escape analysis off, where every allocation the source makes is made, a verification goes from 21904 to 21866 bytes at XMSS h=4, from 50768 to 50632 at XMSS^MT h=20 d=2 and from 95138 to 94808 at d=4; with it on, which is what runs, the difference is not visible at all and the figures move by up to 0.6% the other way, which is the JIT's own inlining and not a cost.
gefeili
More...
2 months ago
The RSA-PSS services now reject a PSSParameterSpec whose trailerField is not 1 with the InvalidAlgorithmParameterException Signature.setParameter declares, and check it ahead of the assignments so a refused spec leaves the engine as it was rather than being half-applied, relates to github #2421.
David Hook
More...
2 months ago
Take over the len-by-n block array a WOTS+ public key and signature each carry rather than copying it in, which leaves the shared check with the check and none of the copy - it is validateShape now, and checkedClone has no callers left. Every array reaching either constructor is built by its caller and handed straight over, and the two classes being package-private and final is what makes that a list of five call sites rather than a guess: getPublicKey and getPublicKeyFromSignature fill a fresh byte[len][] with what chain() returns, sign() likewise, and XMSSReducedSignature's two branches with copyOfRange of the encoding being read and with an empty len-by-n. What has to be checked rather than assumed is that chain()'s returns are its own arrays, and they are because it copies its starting value out at zero steps instead of handing it back: signing reaches that case for every base-w digit of the message that is zero, chaining each from one buffer it reuses across the len chains, and recovery for every digit equal to w - 1, chaining those from the signature's own blocks - so without that copy a signature would hold one array many times over, and a recovered key would share storage with the signature it came from. Generation never reaches it, chaining a fixed w - 1 steps. Nothing escapes that did not before: toByteArray() still copies on the way out, and toNodes(), getBlock() and encodeTo() each say for themselves that their callers only read, so what goes is a copy of an array no one else could reach. It was made once per one-time key, which is once per leaf of every tree built. An h=10 SHA-256 key generation goes from 14644426 to 11056442 bytes, 13.97 MiB to 10.54, and 14301 to 10797 a leaf - a difference of 3504, which is exactly the len + 1 arrays of the copy, 67 of 32 bytes and the array holding them - with signing 28786 to 22106. At SHA-512 it is 40876536 to 29735640, 38.98 MiB to 28.36, and signing 78216 to 56552. Measured in the same harness and the same session against the tree as it stood before the first of these three commits, key generation goes from 36402122 to 11056442 at SHA-256 and from 109262904 to 29735640 at SHA-512. The results are unchanged and are pinned as such rather than assumed: XMSSPromotionCompatibilityTest compares keys, signatures and cross-verification against the deprecated org.bouncycastle.pqc.crypto.xmss copy over six parameter sets and every index of a key, and passes, as do crypto.signers.xmss.AllTests, the provider's XMSSTest and XMSSMTTest and pqc.crypto.test.AllTests. Two tests state the invariants the change now rests on - that compressing a public key leaves the key as it was, the L-tree walk overwriting the array of nodes it is given and never the value inside one, and that no two blocks of a signature are the same array and no block of a recovered key is a block of the signature it came from. The second signs a digest of 0x0f bytes, which is every digit alternately 0 and 15, so each of the len positions is a zero-step chain on one of the two sides. Four mutations confirm those tests reach what they describe - a walk that disturbs a node's value, chain() handing its starting value back at zero steps, one of the four shape checks dropped, and validateShape returning an array other than the one it was given - and two confirm the change is sound: putting both copies back, and handing the walk copies of the blocks rather than the blocks, each leaves every byte the oracle compares where it was.
gefeili
More...
2 months ago
CMS: the RFC 9629 KEMRecipientInfo recipient path no longer lets an oversized kekLength, a sequence size disagreeing with the optional ukm, or a wrap algorithm with no known KEK size escape as an unchecked exception, and now confirms the kekLength against the wrap algorithm as RFC 9629 sec. 3 requires; CMSAuthEnvelopedData and both streaming parsers also gained the malformed-RecipientInfo translation new CMSEnvelopedData(byte[]) has always had, relates to github #2422.
David Hook
More...
2 months ago
←
1
2
…
17
18
19
20
21
22
23
24
25
…
805
806
→
This site uses cookies to give you the best possible experience. By using the site, you consent to our use of cookies. For more information, please see our
Privacy Policy
Agree