Last updated: 2026-June-11
Shamir's Keystore
Abstract
This JCA provider presently implements Shamir's Secret Sharing using Newton Polynomials. Building on this, a KeyStore Engine as defined by the Java Cryptographic Architecture is provided. Such a keystore instance might be unlocked - apart from the master password - by certain subsets of previously computed secret shares. In order to be able to reconstruct the master password a specific number of secret shares equal to (or above) a given threshold must be combined. Shamirs scheme is information-theoretically secure. This means that an attacker does not get any additional information about the original master password with fewer shares as defined by the given threshold. In this way, it is possible to enforce e.g. the four-eye-principle. The provided keystore implementation is PKCS12 compliant and internally relies on the implementation provided by the Java platform.
1. Build
Clone the project (or download and unpack the zip):
$ git clone https://github.com/chr78rm/shamirs-keystore.git
$ cd shamirs-keystore
Maven and a JDK 17+ are required for the build of the multi-module project:
$ mvn clean install
Above command will compile the sources, run the tests and install the provider into the local Maven repo.
Note that the included demo app makes use of the pkix sub-module from the Bouncy Castle crypto library for programmatically generating self-signed X.509 certificates which is something that cannot be easily done with the JDK alone. The library itself depends on the Scala-Library (since the core module containing the actual algorithm is presently written in Scala) and on Jakarta JSON Processing. The latter is merely the specification of an API and hence you additionally need an implementation for that at runtime, e.g. Eclipse Parsson, if you want to use the JCA provider in your applications. See section 6.2 Maven Coordinates for further details.
The project uses JUnit 5 together with AssertJ or rather ScalaTest for unit testing.
![]() |
When using a JDK24+ for the build you will get some warnings regarding calls of terminally deprecated methods in sun.misc.Unsafe by the libraries zero-allocation-hashing-0.16 and scala-library-3.8.3. The latter one is somewhat confusing since it was supposed to be fixed since Scala 3.8.0. This is probably due to tooling(s) compiled against "unsafe" Versions of Scala 3. Scala 3 guarantees backwards compatibility across minor releases, that is libraries compiled against e.g. version 3.3.7 can be used in projects compiled against Scala 3.8.3. (A similar cross compilation and linking between minor versions wasn't possible in Scala 2.) For additional background information, see e.g. REPL still prints LazyVal warnings regarding a similar issue within the Scala command-line interpreter. According to my current understanding, the offending tools are zinc leveraged by the scala-maven-plugin and scalatest or rather the scalatest-maven-plugin. |
I have added an alternative and minimal build tool based on bash scripts and the maven dependency plugin to minimize the exposure against these tools and thus mitigate the risk. The alternative build tool is leveraged by a corresponding maven build profile. This eliminates the warnings due to zinc. The warnings due to scalatest remain. Interestingly some of those warnings show up during the compilation(!) of the test sources, possibly because of the compile time evaluation of some scalatest code.
2. Source Control
The source code is hosted in GitHub: https://github.com/chr78rm/shamirs-keystore.
3. The Algorithm
Consider the polynomial
Pk-1(x) = ak-1xk-1 + ... + a2x2 + a1x + a0
of degree k-1 given in the canonical form. Recall that you need k supporting points to recover a polynomial of degree k-1. Shamir's (k,n) threshold scheme is building upon this property. A trusted authority randomly selects a polynomial Pk-1 and computes n supporting points whereby n >= k applies. The to be shared secret s is encoded as a0. The n supporting points are distributed among the participants. To compute the original secret s the participants must combine k of the supporting points. In order to avoid that an adversary gains any knowledge about the secret by merging less than k supporting points all computations will by implemented by using finite field arithmetic. That means we choose a finite field 𝔽p whereby p is prime and a0 < p applies.
The simplest procedure for reconstructing a polynomial P of degree k-1 with given k supporting points (x0,y0),...,(xk-1,yk-1) is by devising a system of k linear equations. A parabola, for instance, is defined by three supporting points (x0,y0),(x1,y1),(x2,y2). The coefficients a0,a1,a2 can be computed by solving the system of linear equations below:
y0 = a2x02 + a1x0 + a0
y1 = a2x12 + a1x1 + a0
y2 = a2x22 + a1x2 + a0
There are, however, more efficient algorithms. This distribution uses the Newton interpolation method to recover the secret s. A Newton polynomial of degree k-1 is given by
Pk-1(x) = 𝝨 i=0 k-1 ciNi(x)
with Newton coefficients c0,c1,...,ck-1 and the Newton basis polynomials N0 = 1 and Ni = 𝞟 j=0 i-1 (x - xj).
This gives
Pk-1(x) = c0 + c1(x - x0) + c2(x - x0)(x - x1) + ⋯ + ck-1(x - x0) ⋯ (x - xk-2)
By applying x ← x0,x ← x1,x ← x2,... it follows
P(x0) = c0
P(x1) = c0 + c1(x1 - x0)
P(x2) = c0 + c1(x2 - x0) + c2(x2 - x0)(x2 - x1)
P(x3) = c0 + c1(x3 - x0) + c2(x3 - x0)(x3 - x1) + c3(x3 - x0)(x3 - x1)(x3 - x2)
⋮⋮
Since we are interested in recovering the Newton polynomial by using the supporting points we rearrange the equations above:
c0 = y0
c1 = (y1 - c0)/(x1 - x0)
c2 = (y2 - c0 - c1(x2 - x0))/(x2 - x0)(x2 - x1)
c3 = (y3 - c0 - c1(x3 - x0) - c2(x3 - x0)(x3 - x1))/(x3 - x0)(x3 - x1)(x3 - x2)
⋮⋮
Now we can clearly see a recurring pattern. Thus, the Newton coefficients can be computed by a recursive procedure and by memoizing the already calculated coefficients (dynamic programming), see NewtonInterpolation.scala for details.
We need to evaluate the interpolated polynom at least at one point, namely at P(0) = a0 to recover the original secret. An efficient way of doing this is by applying Horner's scheme. The Newton polynomial P of degree k-1 can be rewritten as
Pk-1(x) = c0 + (x - x0)[c1 + (x - x1)[c2 + ⋯ + ck-1(x - xk-2)] ⋯ ]
so that P(x) can be calculated recursively:
b0 = c0 + (x - x0)b1
b1 = c1 + (x - x1)b2
b2 = c2 + (x - x2)b3
⋮⋮
bk-1 = ck-1
where P(x) = b0 .
4. UML Diagrams
4.1 Component Diagrams
4.2 Class Diagram
5. Reports
The two sub modules shamirs-keystore - containing the actual JCA provider - and shamirs-demo are both using JUnit5 for their unit testing. The Maven Surefire Plugin up to version 3.2.5 is confused about JUnit5's nested tests and hence doesn't accurately produce the numbers for the reports. The two linked reports below have been generated by a custom JUnit5 TestExecutionListener during the last build.
| Artifact | Report |
|---|---|
| shamirs-keystore | summary.txt |
| shamirs-demo | summary.txt |
The sub module shamirs-secret-sharing - containing the actual algorithm - is written in Scala and uses ScalaTest for its unit testing. Again a custom Reporter is used to collect the events occurring throughout the execution of the tests. The linked report below has been generated during the last build.
| Artifact | Report |
|---|---|
| shamirs-secret-sharing | summary.txt |
6. Download
6.1 Demo App
Up to version 1.3.3 the demo app had been packaged by the Maven Shade Plugin. Since then, the required (third-party) libraries are wrapped within a separate directory. The subsequently provided downloads contain the demo app and both the core module with the algorithm and the actual JCA provider as well as the remaining third-party libraries.
| Artifact | Archive | Build Time | sha512 checksum |
|---|---|---|---|
| shamirs-demo-1.0.0-beta | shamirs-demo-1.0.0-beta.zip | 2020-05-20 13:50:27.364 +0200 | shamirs-demo-1.0.0-beta.zip.sha512 |
| shamirs-demo-1.0.0-rc1 | shamirs-demo-1.0.0-rc1.zip | 2020-12-18 15:43:09.754 +0100 | shamirs-demo-1.0.0-rc1.zip.sha512 |
| shamirs-demo-1.0.0 | shamirs-demo-1.0.0.zip | 2021-01-06 14:57:47.925 +0100 | shamirs-demo-1.0.0.zip.sha512 |
| shamirs-demo-1.1.0 | shamirs-demo-1.1.0.zip | 2021-05-26 17:20:08.866 +0200 | shamirs-demo-1.1.0.zip.sha512 |
| shamirs-demo-1.2.0 | shamirs-demo-1.2.0.zip | 2022-04-22 14:57:24.886 +0200 | shamirs-demo-1.2.0.zip.sha512 |
| shamirs-demo-1.3.0 | shamirs-demo-1.3.0.zip | 2024-03-12 13:41:47.720 +0100 | shamirs-demo-1.3.0.zip.sha512 |
| shamirs-demo-1.3.1 | shamirs-demo-1.3.1.zip | 2024-06-19 16:36:40.012 +0200 | shamirs-demo-1.3.1.zip.sha512 |
| shamirs-demo-1.3.2 | shamirs-demo-1.3.2.zip | 2024-07-31 15:02:49.280 +0200 | shamirs-demo-1.3.2.zip.sha512 |
| shamirs-demo-1.3.3 | shamirs-demo-1.3.3.zip | 2025-10-30 19:26:44.667 +0100 | shamirs-demo-1.3.3.zip.sha512 |
| shamirs-demo-1.4.0 | shamirs-demo-1.4.0.zip | 2026-05-21 16:31:27.188 +0200 | shamirs-demo-1.4.0.zip.sha512 |
Note that the demo app includes binaries from external open source projects, namely the Scala-Library, the Jakarta JSON-Processing implementation Eclipse Parsson and the pkix sub-module from Bouncy Castle. Section 7.1 Demo App explains how to use the demo app.
6.2 Maven Coordinates
The KeyStore engine together with the relevant artifacts had been deployed to Maven Central and can be used within your applications by referencing the subsequent Maven coordinates:
<dependency> <groupId>de.christofreichardt</groupId> <artifactId>shamirs-keystore</artifactId> <version>1.4.0</version> </dependency>
You will additionally need an implementation for the Jakarta JSON Processing API at runtime, e.g.
<dependency> <groupId>org.eclipse.parsson</groupId> <artifactId>jakarta.json</artifactId> <version>1.1.7</version> <scope>runtime</scope> </dependency>
Depending on your deployment the latter runtime dependency might not be necessary, e.g. if you are using a Jakarta EE application server. Starting with version 1.3.0 the library uses the new jakarta.json namespace instead of the legacy javax.json and should therefore be compatible with Jakarta EE 9 upwards. An alternative to Eclipse Parsson is Joy but Eclipse Parsson seems to be more actively maintained and it is the reference implementation.
Section 7.2 Keystore Engine explains how to use the provider within your applications.
6.3 Project Dependencies
These are the third-party dependencies of the latest version deployed to Maven Central:
| GroupId | ArtifactId | Version | Scope | License |
|---|---|---|---|---|
| de.christofreichardt | tracelogger | 1.10.0 | compile | Apache License, Version 2.0 |
| org.scala-lang | scala-library | 3.8.3 | compile | Apache License, Version 2.0 |
| jakarta.json | jakarta.json-api | 2.1.3 | compile | GNU General Public License Version 2 with Classpath Exception, Eclipse Public License 2.0 |
| org.eclipse.parsson | jakarta.json | 1.1.7 | provided | GNU General Public License Version 2 with Classpath Exception, Eclipse Public License 2.0 |
The demo app has an additional dependency on Bouncy Castle's pkix sub-module:
| GroupId | ArtifactId | Version | Scope | License |
|---|---|---|---|---|
| org.bouncycastle | bcpkix-jdk18on | 1.84 | compile | MIT License |
7. User Manual
7.1 Demo App
Download the demo app and unzip the archive into a directory of your choice. Starting with Version 1.4.0 you will need a JDK 17+ for the execution of the app. I am using the Git Bash for this manual but the default command line interpreter of Windows (cmd) works as well. Of course you can use the GNU Bash on Linux systems too. I have tested the distribution with the Git Bash (2.54.0) on Windows 11, with Windows Cmd on Windows 11 and with the GNU Bash on Ubuntu 24.04.4 LTS (Noble Numbat) by randomly using a JDK 17, JDK 21 or JDK 25. I'm using the latest Azul Zulu Builds of OpenJDK for the LTS releases.
I have moved away from creating an uber-jar by shading. Instead the required (third-party) libraries are now separately packaged. Therefore, after unzipping the distribution exhibits the following structure:
shamirs-demo/ ├── log ├── src │ └── main │ ├── java │ │ └── de │ │ └── christofreichardt │ │ └── jca │ │ └── shamirsdemo │ │ ├── AbstractMenu.java │ │ ├── App.java │ │ ├── AppCallback.java │ │ ├── KeyStoreMenu.java │ │ ├── MainMenu.java │ │ └── Menu.java │ └── resources │ └── de │ └── christofreichardt │ └── jca │ └── trace-config.xml ├── target │ ├── lib │ │ ├── bcpkix-jdk18on-1.84.jar │ │ ├── bcprov-jdk18on-1.84.jar │ │ ├── bcutil-jdk18on-1.84.jar │ │ ├── jakarta.json-1.1.7.jar │ │ ├── jakarta.json-api-2.1.3.jar │ │ ├── scala-library-3.8.3.jar │ │ ├── scala3-library_3-3.8.3.jar │ │ ├── shamirs-keystore-1.4.0.jar │ │ ├── shamirs-secret-sharing-1.4.0.jar │ │ └── tracelogger-1.10.0.jar │ └── shamirs-demo-1.4.0.jar ├── workspace │ └── my-workspace-0 │ ├── donalds-keys.p12 │ ├── test-0.json │ ├── test-1.json │ ├── test-2.json │ ├── test-3.json │ ├── test-4.json │ ├── test-5.json │ ├── test-6.json │ └── test.json ├── LICENCE.txt ├── NOTICE.txt ├── run-shamirs-demo.bat ├── run-shamirs-demo.sh └── winpty-shamirs-demo.sh
![]() |
Starting with JDK 22, Java has used an internal JLine instance as the default Console implementation to improve the user experience of programs using the Console API, see JLine As The Default Console Provider. Initially, this change caused some problems especially with the bulk read operations when using the associated Reader of the Console, see Console#reader(). As of JDK 25 those operations seem to work properly again - I haven't checked JDK 24, though. Therefore the included launch scripts starting with version 1.3.3 (see table below) are now setting up JLine as Console provider. If needed, the older behaviour can be restored by passing the argument --base to the launch scripts. I am no longer seeing the now infamous warnings about calling terminally deprecated methods in sun.misc.Unsafe when executing the demo by using a JDK 24+. This had previously been an issue with the lazy val definitions employed by the library. Therefore you don't need disabling the warning by applying the --sun-misc-unsafe option, see below, and the 1.4.0 version of the library is probably safe to use even when the plug is finally pulled by the OpenJDK team sometime in the future. But unfortunately the issue hasn't been completely solved, see my remarks concerning the build. |
Refer to the table below for the selection of a suitable launch script depending on the environment:
| Git Bash on Windows | Windows Cmd | Linux Bash |
|---|---|---|
| run-shamirs-demo.sh [option]... | run-shamirs-demo.bat [option]... | run-shamirs-demo.sh [option]... |
| winpty-shamirs-demo.sh [option]... |
whereby option is one of --jline (the default), --base, --echo, --no-bulk or --sun-misc-unsafe. With --base the older Console behaviour can be restored but then you might get none dependent on your environment (e.g. older Git Bash versions). --echo and --no-bulk are maintained for historical reasons. --sun-misc-unsafe disables the mentioned warning about the calling of a terminally deprecated method in sun.misc.Unsafe. This option is only valid for JDK 24+.
$ cd shamirs-demo $ ls LICENCE.txt log/ NOTICE.txt run-shamirs-demo.bat run-shamirs-demo.sh* src/ target/ winpty-shamirs-demo.sh* workspace/ $ java -version openjdk version "26.0.1" 2026-04-21 OpenJDK Runtime Environment (build 26.0.1+8-34) OpenJDK 64-Bit Server VM (build 26.0.1+8-34, mixed mode, sharing) $ ./run-shamirs-demo.sh ... +---------------+ | Shamir's Demo | +---------------+ Current time: 2026-05-28T17:07:26.0359069 Workspace: 2026-05-28 2026-05-28-> Main menu (s)plit password (m)erge password (o)pen workspace (c)reate keystore (lo)ad keystore (li)st workspace (e)xit 2026-05-28->
The string 2026-05-28 left from the arrow denotes the current date and workspace. You automatically get a new one on every day you are using the app. The provided commands are invoked by their given shortcuts. Since this newly created workspace is empty we begin with splitting a password:
2026-05-28-> s 2026-05-28-> split password 2026-05-28-> Password ([A-Za-z0-9-]{8,45}) [4Mzy4EIqijzUTZyg1z2P7SmyH]: 2026-05-28-> Number of shares ([0-9]+): 12 2026-05-28-> Threshold ([0-9]+): 4 2026-05-28-> Name of partition ([A-Za-z]{1,10}): demo 2026-05-28-> Number of slices ([0-9]+): 7 2026-05-28-> Size[i=0, sum=0] ([0-9]+): 4 2026-05-28-> Size[i=1, sum=4] ([0-9]+): 2 2026-05-28-> Size[i=2, sum=6] ([0-9]+): 2 2026-05-28-> Size[i=3, sum=8] ([0-9]+): 1 2026-05-28-> Size[i=4, sum=9] ([0-9]+): 1 2026-05-28-> Size[i=5, sum=10] ([0-9]+): 1 2026-05-28-> Size[i=6, sum=11] ([0-9]+): 1 2026-05-28-> Certification method (All|Slices|None) [None]: All ------------------------------------------------------------- certificationResult = CertificationResult[falsified=298, verified=495]
The app will make a password proposal (seen within the square brackets). Every user provided input will be matched against the regular expressions given in the round brackets. In our example we instructed to generate 12 shares whereas 4 of them are needed to recover the original password. The shares are grouped within a partition named demo. The 12 shares were divided into 7 slices. The first slice had been given 4 shares. The next two slices had both received 2 shares and the remaining slices had been in each case given 1 share. The found solution can be optionally certified. The preset is no certification at all. A certification by Slices means that all slice combinations with a sharepoint count less than the threshold will be falsified and vice versa all slice combinations with a sharepoint count equal to or above the threshold will be verified. The certification method All means that regardless of the chosen slices all combinations of shares below the threshold will be falsified and all combination of shares that equals the threshold will be verified. These are potentially very expensive operations depending on the number of combinations that have to be considered. You can consult WolframAlpha for the computation of the binomial coefficients, e.g. 12 choose 4 gives 495 as expected. A negative outcome would raise an AssertionError.
(By pure chance a sharepoint combination below the threshold might result in the same y-intercept as the actual solution, that should be almost impossible if you are using long enough passwords which result in correspondingly big-sized finite fields).
Now, open another console and review the content of the your workspace directory (workspace/yyyy-MM-dd):
$ ls workspace/2026-05-28/ demo.json demo-0.json demo-1.json demo-2.json demo-3.json demo-4.json demo-5.json demo-6.json
The file demo.json contains all of the generated shares, demo-0.json four of them, demo-1.json two and so on. The idea is that we have seven participants in our example. Each of them will be given one slice. This means the participant owning the slice demo-0.json is able to recover the password by herself whereas the owner of demo-1.json must team up with the owner of demo-2.json or with two owners of the remaining slices and so on. Now switch back to the demo app and invoke (li)st workspace:
2026-05-28-> li 2026-05-28-> list workspace 2026-05-28-> Partitions: [demo] 2026-05-28-> Slices(demo): [demo-0.json, demo-1.json, demo-2.json, demo-3.json, demo-4.json, demo-5.json, demo-6.json] 2026-05-28-> Keystores: []
We have already seen that. Now lets recover the original password by combining the slices demo-1.json, demo-3.json and demo-6.json:
2026-05-28-> m 2026-05-28-> merge password 2026-05-28-> Slices (([A-Za-z]{1,10}-[0-9]+\.json(,( )*)?)+([A-Za-z]{1,10}-[0-9]+\.json)?): demo-1.json, demo-3.json, demo-6.json 2026-05-28-> password = 4Mzy4EIqijzUTZyg1z2P7SmyH
As expected. Merging works, inter alia, by providing a list of Paths
to the different slices and then applying Newtons Interpolation. That means the slices
need not necessarily be located together in one directory as in our demo. In fact they could be distributed over the whole filesystem and could be
located even on remote devices. Think of plugged-in USB memory sticks or network filesystems. Future versions might interpret the Paths as
URIs and could fetch the slices via the internet if required.
Now, let's create a keystore:
2026-05-28-> Main menu (s)plit password (m)erge password (o)pen workspace (c)reate keystore (lo)ad keystore (li)st workspace (e)xit 2026-05-28-> c 2026-05-28-> create keystore 2026-05-28-> Keystore name ([A-Za-z-]{1,20}): donalds-keys 2026-05-28-> Slices (([A-Za-z]{1,10}-[0-9]+\.json(,( )*)?)+([A-Za-z]{1,10}-[0-9]+\.json)?): demo-3.json, demo-4.json, demo-5.json, demo-6.json +---------------+ | Shamir's Demo | +---------------+ Current time: 2026-05-28T17:23:08.5051034 Workspace: 2026-05-28 2026-05-28-> KeyStore menu [donalds-keys] (l)ist entries (p)rivate key (s)ecret key (c)ertificate (m)ain menu 2026-05-28->
We used four of the slices containing a single share to produce the credentials for the keystore. The demo app switched to a submenu regarding keystore functionality. At present the keystore is empty. A Java PKCS12 keystore can contain three different types of entries: Private Key, Secret Key and Certificate entries. Private and Secret Keys need protection whereas certificates need not since latter are public. Hence we will create a Private Key. A Private Key is always accompanied with a certificate that attests the associated Public Key. From the start these certificates are self-signed but could be the result from a PKCS10 certificate request too.
2026-05-28-> p 2026-05-28-> private key 2026-05-28-> Keygenerator algorithm (DSA|RSA|EC): EC 2026-05-28-> Validity ([0-9]+): 100 2026-05-28-> Common Name ([A-Za-z- ]{5,30}): Donald Duck 2026-05-28-> Locality ([A-Za-z- ]{5,30}): Entenhausen 2026-05-28-> State ([A-Za-z- ]{5,30}): Bayern 2026-05-28-> Country ([A-Za-z- ]{5,30}): Deutschland 2026-05-28-> Alias ([a-z0-9-]{5,25}): donalds-private-ec-key
We specified Elliptic Curve (EC) as KeyPairGenerator algorithm and a validity of 100 days for the accompanying self-signed certificate. The remaining parameter constitute the so called Distinguished Name.
Now, list the entries so far:
2026-05-28-> l 2026-05-28-> list entries 2026-05-28-> donalds-private-ec-key: friendlyName=donalds-private-ec-key, localId=54:69:6d:65:20:31:37:37:39:39:38:32:30:30:37:31:33:38, algorithm=EC, keytype=Private Key
Go back to main menu:
2026-05-28-> m 2026-05-28-> main menu +---------------+ | Shamir's Demo | +---------------+ Current time: 2026-05-28T17:28:44.0114178 Workspace: 2026-05-28 2026-05-28-> Main menu (s)plit password (m)erge password (o)pen workspace (c)reate keystore (lo)ad keystore (li)st workspace (e)xit 2026-05-28->
Now, list the workspace again:
2026-05-28-> li 2026-05-28-> list workspace 2026-05-28-> Partitions: [demo] 2026-05-28-> Slices(demo): [demo-0.json, demo-1.json, demo-2.json, demo-3.json, demo-4.json, demo-5.json, demo-6.json] 2026-05-28-> Keystores: [donalds-keys]
Again, merge some of the slices to recover the password of the keystore:
2026-05-28-> m 2026-05-28-> merge password 2026-05-28-> Slices (([A-Za-z]{1,10}-[0-9]+\.json(,( )*)?)+([A-Za-z]{1,10}-[0-9]+\.json)?): demo-1.json, demo-2.json 2026-05-28-> password = 4Mzy4EIqijzUTZyg1z2P7SmyH
Switch to a separate console since we want to investigate the keystore with keytool. Note that your own workspace is probably different.
$ cd workspace/2026-05-28 # workspace/yyyy-MM-dd $ ls demo.json demo-0.json demo-1.json demo-2.json demo-3.json demo-4.json demo-5.json demo-6.json donalds-keys.p12 $ keytool -J-Duser.language=en -list -keystore donalds-keys.p12 -storepass 4Mzy4EIqijzUTZyg1z2P7SmyH -storetype pkcs12 -v Keystore type: PKCS12 Keystore provider: SUN Your keystore contains 1 entry Alias name: donalds-private-ec-key Creation date: 28 May 2026 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: C=Deutschland, ST=Bayern, L=Entenhausen, CN=Donald Duck Issuer: C=Deutschland, ST=Bayern, L=Entenhausen, CN=Donald Duck Serial number: 19e6f31fa28 Valid from: Thu May 28 17:26:46 CEST 2026 until: Sat Sep 05 17:26:46 CEST 2026 Certificate fingerprints: SHA1: 1D:AF:4F:AA:98:0D:94:0D:E1:B8:F6:7D:1A:D5:E5:DF:86:FE:7F:4D SHA256: AA:7F:C4:F0:96:47:4D:64:77:82:41:D4:63:77:C5:13:E9:EB:10:46:57:48:E8:C0:61:18:51:D1:77:C3:58:DC Signature algorithm name: SHA256withECDSA Subject Public Key Algorithm: 521-bit EC (secp521r1) key Version: 3 ******************************************* ********************************************
Note that we used the recovered password in combination with keytool. This will be the end of our little tour. There are other options to consider and there are some rough edges as well. For example ChaCha20 secret keys don't work since the underlying keystore implementation of the JDK doesn't recognize them.
2026-05-28-> Main menu (s)plit password (m)erge password (o)pen workspace (c)reate keystore (lo)ad keystore (li)st workspace (e)xit 2026-05-28-> e 2026-05-28-> exit
7.2 Keystore Engine
See section 6.2 Maven Coordinates for the version of the present distribution. Subsequently, I give a simple example how to use the keystore engine within your application. First, you need to install the provider:
|
|
On my system I'm getting the following output:
provider[SUN] = SUN (DSA key/parameter generation; DSA signing; SHA-1, MD5 digests; SecureRandom; X.509 certificates; PKCS12, JKS & DKS keystores; PKIX CertPathValidator; PKIX CertPathBuilder; LDAP, Collection CertStores, JavaPolicy Policy; JavaLoginConfig Configuration) provider[SunRsaSign] = Sun RSA signature provider provider[SunEC] = Sun Elliptic Curve provider provider[SunJSSE] = Sun JSSE provider(PKCS12, SunX509/PKIX key/trust factories, SSLv3/TLSv1/TLSv1.1/TLSv1.2/TLSv1.3/DTLSv1.0/DTLSv1.2) provider[SunJCE] = SunJCE Provider (implements RSA, DES, Triple DES, AES, Blowfish, ARCFOUR, RC2, PBE, Diffie-Hellman, HMAC, ChaCha20, DHKEM, ML-KEM, and HKDF) provider[SunJGSS] = Sun (Kerberos v5, SPNEGO) provider[SunSASL] = Sun SASL provider(implements client mechanisms for: DIGEST-MD5, EXTERNAL, PLAIN, CRAM-MD5, NTLM; server mechanisms for: DIGEST-MD5, CRAM-MD5, NTLM) provider[XMLDSig] = XMLDSig (DOM XMLSignatureFactory; DOM KeyInfoFactory; C14N 1.0, C14N 1.1, Exclusive C14N, Base64, Enveloped, XPath, XPath2, XSLT TransformServices) provider[SunPCSC] = Sun PC/SC provider provider[JdkLDAP] = JdkLDAP Provider (implements LDAP CertStore) provider[JdkSASL] = JDK SASL provider(implements client and server mechanisms for GSSAPI) provider[SunMSCAPI] = Sun's Microsoft Crypto API provider provider[SunPKCS11] = Unconfigured and unusable PKCS11 provider provider[Christofs Crypto Lib] = A pkcs12 KeyStore implementation which supports shared passwords.
As can be seen the recently installed provider is the least significant one. The next statement requests the desired keystore engine:
|
|
In order to make it simple I'm building upon from the previous section 7.1 Demo App by assuming the over there generated shares and keystore within a subdirectory test-workspace.
|
|
Now we have everything together to load the keystore:
|
|
For further examples I am referring to the source code of the demo app.
8. API Documentation
| Module | API Documentation |
|---|---|
| shamirs-secret-sharing | shamirs-secret-sharing 1.3.0 API |
| shamirs-keystore | shamirs-keystore 1.3.0 API |
9. JSON Schema
9.1 Definitions
| Name | Type | Comment |
|---|---|---|
| PartitionId | string | An Universally Unique Identifier |
| Prime | number | Interpreted as BigInteger |
| Threshold | number | Interpreted as 32-Bit Integer |
| SharePoints | array of SharePoint |
| Name | Type | Comment |
|---|---|---|
| x | number | Interpreted as BigInteger |
| y | number | Interpreted as BigInteger |
9.2 Example
{ "PartitionId": "242e3fda-9c64-45f3-b40d-52bdcf3db8ca", "Prime": 341494281274260103295293103126026736379588956778975874386655979, "Threshold": 4, "SharePoints": [ { "SharePoint": { "x": 115100532256754722181886210957822661071917163545119627890196490, "y": 156627716112697373056443201494624435073664977495521717817469760 } }, { "SharePoint": { "x": 22609839444392691960191176427554135723838878004964001329002259, "y": 316594037802106556387665640965532931520415012810267565947034427 } } ] }
