Crypto-View

Peergos/Peergos

Readiness score
70 of 100
How this is calculated · previous scan 70
Cryptographic posture
Quantum-vulnerable 6 Already broken 4 Reduced margin 14 Could not be determined 59 Quantum-safe 47
To address35
Key establishment2
Inventory only1
Total findings131
What was analysed
Branch master
Commit 61e70c358790a85181470e04bebcf0bdb062e477 Merge pull request #1422 from Peergos/feat/force-migrate
Committed 2026-09-09 06:40 UTC
Scanned 2026-09-10 00:00 UTC 1 day ago
Coverage 1110 files, 1094 java

Earlier scans of this repository

13 scans · score 86 → 20 · compare any two
13 scans · 86 → 20 (down 66). The filled point is the scan you are reading.
Scanned Commit Score To address
3 hours ago 21bc1cc602e9 master 20 69 Compare
4 hours ago 02e34c729dcd master 55 39 Compare
18 hours ago f2cdc1955e60 85 16 Compare
20 hours ago 61e70c358790 master 55 39 Compare
23 hours ago 61e70c358790 master 55 39 Compare
1 day ago 61e70c358790 master 55 39 Compare
1 day ago 61e70c358790 master 55 39 Compare
1 day ago this scan 61e70c358790 master 70 35
3 days ago 810190f8cf0f master 70 35 Compare
3 days ago 810190f8cf0f master 70 35 Compare
4 days ago 93072f33c9bb master 70 35 Compare
10 days ago 8e2e3baf101d master 70 35 Compare
11 days ago f2cdc1955e60 86 14 Compare

Every repository in this history is re-scanned weekly.

List of cryptographic assets

MD5 Already broken 4 places See details

Hash algorithm through the JCA

`MessageDigest.getInstance()`. MD5 and SHA-1 are reported as already broken; SHA-256 is reported as a reduced margin rather than a defect.

This is already unsafe today, with no quantum computer involved. Practical chosen-prefix collisions exist; MD5 has no remaining security as a digest.

What to do. SHA-256 as the floor, SHA-384 where the digest protects something that must remain verifiable for decades.

  1. src/peergos/server/storage/S3BucketSync.java:103 MessageDigest md = MessageDigest.getInstance("MD5");
  2. src/peergos/server/tests/ThumbnailCacheSeederTests.java:37 test path byte[] d = MessageDigest.getInstance("MD5").digest(s.getBytes(StandardCharsets.UTF_8));
  3. src/peergos/server/webdav/ThumbnailCacheSeeder.java:154 byte[] digest = MessageDigest.getInstance("MD5").digest(s.getBytes(StandardCharsets.UTF_8));
  4. src/peergos/server/webdav/modeshape/webdav/WebDavServletBean.java:58 MD5_HELPER = MessageDigest.getInstance("MD5");
java.messagedigest · CWE-328
Ed25519255-bitother/Ed25519 Quantum-vulnerable 1 place See details

Classical key pair generated through the JCA

`KeyPairGenerator.getInstance()` with a classical algorithm. The concrete family and, where an `initialize()` call is close enough to read, the key size are resolved from the source and reported on the finding.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Broken by Shor's algorithm on a cryptographically relevant quantum computer.

What to do. Generate the classical key alongside an ML-KEM or ML-DSA key and carry both until relying parties accept the post-quantum one.

  1. src/peergos/server/tests/NitrokeyWebauthn.java:67 test path this.keys = KeyPairGenerator.getInstance("Ed25519").generateKeyPair();
java.keypairgenerator · CWE-327
Ed25519255-bitother/Ed25519 Quantum-vulnerable 1 place See details

Classical signature algorithm through the JCA

`Signature.getInstance()` with a classical algorithm. The digest and the key algorithm are split out of the JCA name, so `SHA1withRSA` reports both the broken digest and the quantum-vulnerable key.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Broken by Shor's algorithm on a cryptographically relevant quantum computer.

What to do. ML-DSA-65 (FIPS 204). Where the verifier cannot be changed, sign twice and publish both signatures.

  1. src/peergos/server/tests/NitrokeyWebauthn.java:76 test path Signature sig = Signature.getInstance("Ed25519");
java.signature · CWE-327
TLS Quantum-vulnerable Recorded traffic 1 place See details

TLS cipher suites pinned in configuration

An `ssl_ciphers`, `SSLCipherSuite` or `ssl-default-bind-ciphers` directive. Every suite available today uses a classical key exchange; a suite naming RC4, DES, 3DES, EXPORT or NULL is broken now.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Every TLS cipher suite in general use negotiates a classical key exchange, so a recorded session is decryptable once that exchange falls.

What to do. Remove anything below TLS 1.2. The key exchange changes when the server software offers a hybrid group, not before.

config.tls-ciphers · CWE-757
TLS Quantum-vulnerable Recorded traffic 1 place See details

TLS context created in code

`SSLContext.getInstance()`. The protocol version is reported; the key exchange it negotiates is classical in every TLS 1.2 and 1.3 cipher suite available today.

A quantum computer of sufficient size breaks this completely. It has to be replaced, not tuned. Every TLS cipher suite in general use negotiates a classical key exchange, so a recorded session is decryptable once that exchange falls.

What to do. Keep TLS 1.3, and track the hybrid key-exchange groups as they reach the JDK. TLS is where harvest-now-decrypt-later exposure is largest.

  1. src/peergos/server/UserService.java:194 SSLContext sslContext = SSLContext.getInstance("TLS");
java.sslcontext · CWE-757
SHA-256 Reduced margin 13 places See details

Hash algorithm through the JCA

`MessageDigest.getInstance()`. MD5 and SHA-1 are reported as already broken; SHA-256 is reported as a reduced margin rather than a defect.

A quantum computer weakens this but does not break it. Increasing the key or digest size restores the margin. Pre-image resistance falls to about 128 bits of quantum work. Adequate for most uses; SHA-384 restores the full margin where a signature must last decades.

What to do. SHA-256 as the floor, SHA-384 where the digest protects something that must remain verifiable for decades.

  1. src/peergos/server/cfapi/CloudFilesMount.java:733 java.security.MessageDigest md = java.security.MessageDigest.getInstance("SHA-256");
  2. src/peergos/server/crypto/hash/ScryptJava.java:116 MessageDigest chunkHash = MessageDigest.getInstance("SHA-256");
  3. src/peergos/server/crypto/hash/ScryptJava.java:124 chunkHash = MessageDigest.getInstance("SHA-256");
  4. src/peergos/server/storage/LocalS3Handler.java:429 return MessageDigest.getInstance("SHA-256").digest(data);
  5. src/peergos/server/storage/RAMStorage.java:272 MessageDigest md = MessageDigest.getInstance("SHA-256");
  6. src/peergos/server/sync/PeergosSyncFS.java:294 MessageDigest chunkHash = MessageDigest.getInstance("SHA-256");
  7. src/peergos/server/sync/PeergosSyncFS.java:303 chunkHash = MessageDigest.getInstance("SHA-256");
  8. src/peergos/server/tests/NitrokeyWebauthn.java:150 test path return MessageDigest.getInstance("SHA-256").digest(in);
  9. src/peergos/server/tests/TransactionsStoreTests.java:44 test path MessageDigest md = MessageDigest.getInstance("SHA-256");
  10. src/peergos/server/tests/VersionedWriteOnlyStorage.java:250 test path MessageDigest md = MessageDigest.getInstance("SHA-256");
  11. src/peergos/server/tests/WriteOnlyStorage.java:221 test path MessageDigest md = MessageDigest.getInstance("SHA-256");
  12. src/peergos/server/webauthn/LinuxSecurityKey.java:49 return MessageDigest.getInstance("SHA-256").digest(data);
  13. src/peergos/server/webdav/caldav/AppDataStore.java:480 MessageDigest digest = MessageDigest.getInstance("SHA-256");
java.messagedigest · CWE-328
SHA3-256 Reduced margin 1 place See details

Hash algorithm through the JCA

`MessageDigest.getInstance()`. MD5 and SHA-1 are reported as already broken; SHA-256 is reported as a reduced margin rather than a defect.

A quantum computer weakens this but does not break it. Increasing the key or digest size restores the margin. Grover's algorithm halves the effective strength; the parameter, not the design, is the problem.

What to do. SHA-256 as the floor, SHA-384 where the digest protects something that must remain verifiable for decades.

  1. src/peergos/server/crypto/asymmetric/mlkem/fips203/hash/MLKEMHash.java:42 sha3Hash256 = MessageDigest.getInstance("SHA3-256");
java.messagedigest · CWE-328
unknown Could not be determined 10 places See details

Non-cryptographic randomness near key material

`new Random()` or `Math.random()` in a file that also imports `java.security`, `javax.crypto` or BouncyCastle. `java.util.Random` is a linear congruential generator and its output is predictable from a handful of samples. The import check is what keeps this from firing on every retry jitter and test fixture in the tree.

Part of this code uses a predictable source of random numbers. If any key comes from it, that key can be guessed today, with no quantum computer needed.

What to do. `java.security.SecureRandom`. This is a classical defect, not a quantum one, and it is worth fixing first.

  1. src/peergos/server/tests/BackupCodesTest.java:42 test path new Random(42).nextBytes(credentialId);
  2. src/peergos/server/tests/RamUserTests.java:456 test path new Random(7).nextBytes(content);
  3. src/peergos/server/tests/RamUserTests.java:847 test path Random random = new Random(666);
  4. src/peergos/server/tests/RamUserTests.java:894 test path Random random = new Random(666);
  5. src/peergos/server/tests/RamUserTests.java:934 test path new Random(42).nextBytes(fileData);
  6. src/peergos/server/tests/RamUserTests.java:969 test path Random random = new Random(666);
  7. src/peergos/server/tests/RamUserTests.java:1009 test path Random random = new Random(666);
  8. src/peergos/server/tests/RamUserTests.java:1331 test path new Random(42).nextBytes(big);
  9. src/peergos/server/tests/RamUserTests.java:1433 test path new Random(7).nextBytes(noisy);
  10. src/peergos/server/tests/RamUserTests.java:1459 test path new Random(42).nextBytes(secretData);
java.random.insecure · CWE-338
unknown Could not be determined 2 places See details

Key pair algorithm chosen at runtime

`KeyPairGenerator.getInstance(x)` where the argument is an identifier. The algorithm cannot be resolved without running the program, so this is reported as an unknown rather than assumed to be classical.

This code picks its encryption method while it runs, so a scan cannot tell which one it ends up using. Somebody has to check the configuration.

What to do. Trace the value to its configuration source and record the concrete algorithm in the cryptographic inventory by hand.

  1. src/peergos/server/tests/fips203/FIPS203Tests.java:144 test path Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
  2. src/peergos/server/tests/fips203/FIPS203Tests.java:165 test path Cipher decipher = Cipher.getInstance(CIPHER_ALGORITHM);
java.keypairgenerator.variable · CWE-327
unknown Could not be determined 1 place See details

Key store holding classical key material

`KeyStore.getInstance("JKS"|"PKCS12"|"BCFKS")`. The store format itself is not the issue; it is the inventory point where the classical private keys of this application live.

This is the application's key cupboard. It is worth knowing what is in it before planning any replacement.

What to do. Record which keys this store holds. A key store is where a migration either happens or silently does not.

  1. src/peergos/server/UserService.java:371 KeyStore ks = KeyStore.getInstance("PKCS12");
java.keystore
ML-KEM-768 Quantum-safe 26 places See details

Post-quantum algorithm through BouncyCastle

A `org.bouncycastle.pqc` class. This is migration work already in progress and is recorded so the inventory shows what has been done, not only what is outstanding.

This is already a quantum-safe algorithm. It is listed so the report shows the work that has been completed.

What to do. None. Confirm the parameter set matches the required NIST category.

  1. src/peergos/server/crypto/asymmetric/mlkem/JavaMlkem.java:10 import peergos.server.crypto.asymmetric.mlkem.fips203.key.mlkem.MLKEMDecapsulationKey;
  2. src/peergos/server/crypto/asymmetric/mlkem/fips203/MimicloneFIPS203.java:5 import peergos.server.crypto.asymmetric.mlkem.fips203.decaps.mlkem.MLKEMDecapsulator;
  3. src/peergos/server/crypto/asymmetric/mlkem/fips203/codec/MLKEMCodec.java:11 public class MLKEMCodec implements Codec {
  4. src/peergos/server/crypto/asymmetric/mlkem/fips203/decaps/mlkem/MLKEMDecapsulator.java:10 import peergos.server.crypto.asymmetric.mlkem.fips203.hash.MLKEMHash;
  5. src/peergos/server/crypto/asymmetric/mlkem/fips203/decaps/provider/MLKEMDecapsulatorProvider.java:5 import peergos.server.crypto.asymmetric.mlkem.fips203.decaps.mlkem.MLKEMDecapsulator;
  6. src/peergos/server/crypto/asymmetric/mlkem/fips203/decrypt/kpke/KPKEDecryptor.java:5 import peergos.server.crypto.asymmetric.mlkem.fips203.codec.MLKEMCodec;
  7. src/peergos/server/crypto/asymmetric/mlkem/fips203/encaps/mlkem/MLKEMEncapsulation.java:5 import peergos.server.crypto.asymmetric.mlkem.fips203.key.mlkem.MLKEMSharedSecretKey;
  8. src/peergos/server/crypto/asymmetric/mlkem/fips203/encaps/mlkem/MLKEMEncapsulator.java:9 import peergos.server.crypto.asymmetric.mlkem.fips203.hash.MLKEMHash;
  9. src/peergos/server/crypto/asymmetric/mlkem/fips203/encaps/provider/MLKEMEncapsulationProvider.java:6 public class MLKEMEncapsulationProvider implements KEMSpi.EncapsulatorSpi {
  10. src/peergos/server/crypto/asymmetric/mlkem/fips203/encrypt/kpke/KPKEEncryptor.java:5 import peergos.server.crypto.asymmetric.mlkem.fips203.codec.MLKEMCodec;
  11. src/peergos/server/crypto/asymmetric/mlkem/fips203/hash/MLKEMHash.java:13 public class MLKEMHash implements Hash {
  12. src/peergos/server/crypto/asymmetric/mlkem/fips203/key/gen/mlkem/MLKEMKeyPairGenerator.java:5 import peergos.server.crypto.asymmetric.mlkem.fips203.codec.MLKEMCodec;
  13. src/peergos/server/crypto/asymmetric/mlkem/fips203/key/gen/provider/MLKEMKeyGenerationProvider.java:9 public class MLKEMKeyGenerationProvider extends KeyPairGeneratorSpi {
  14. src/peergos/server/crypto/asymmetric/mlkem/fips203/key/mlkem/MLKEMDecapsulationKey.java:7 public class MLKEMDecapsulationKey implements DecapsulationKey {
  15. src/peergos/server/crypto/asymmetric/mlkem/fips203/key/mlkem/MLKEMEncapsulationKey.java:7 public class MLKEMEncapsulationKey implements EncapsulationKey {
  16. src/peergos/server/crypto/asymmetric/mlkem/fips203/key/mlkem/MLKEMKeyPair.java:9 public class MLKEMKeyPair implements KeyPair {
  17. src/peergos/server/crypto/asymmetric/mlkem/fips203/key/mlkem/MLKEMSharedSecretKey.java:7 public class MLKEMSharedSecretKey implements SharedSecretKey {
  18. src/peergos/server/crypto/asymmetric/mlkem/fips203/message/MLKEMCipherText.java:3 public class MLKEMCipherText implements CipherText {
  19. src/peergos/server/crypto/asymmetric/mlkem/fips203/provider/MLKEMProvider.java:4 import peergos.server.crypto.asymmetric.mlkem.fips203.decaps.provider.MLKEMDecapsulatorProvider;
  20. src/peergos/server/crypto/asymmetric/mlkem/fips203/provider/MimicloneSecurityProvider.java:5 import peergos.server.crypto.asymmetric.mlkem.fips203.key.gen.provider.MLKEMKeyGenerationProvider;
  21. src/peergos/server/crypto/asymmetric/mlkem/fips203/sample/MLKEMSampler.java:14 test path public class MLKEMSampler implements Sampler {
  22. src/peergos/server/crypto/asymmetric/mlkem/fips203/transform/MLKEMTransformer.java:11 public class MLKEMTransformer implements Transformer {
  23. src/peergos/server/tests/MLKEMTests.java:13 test path import peergos.server.crypto.asymmetric.mlkem.fips203.message.MLKEMCipherText;
  24. src/peergos/server/tests/fips203/decaps/mlkem/MLKEMDecapsulatorTests.java:8 test path import peergos.server.crypto.asymmetric.mlkem.fips203.decaps.mlkem.MLKEMDecapsulator;
  25. src/peergos/server/tests/fips203/encaps/mlkem/MLKEMEncapsulatorTests.java:8 test path import peergos.server.crypto.asymmetric.mlkem.fips203.encaps.mlkem.MLKEMEncapsulator;
  26. src/peergos/server/tests/fips203/key/gen/mlkem/MLKEMKeyGeneratorTests.java:11 test path import peergos.server.crypto.asymmetric.mlkem.fips203.key.gen.mlkem.MLKEMKeyPairGenerator;
java.bouncycastle.pqc
CSPRNG Quantum-safe 13 places See details

Random number generation

`SecureRandom`. A platform CSPRNG is not a quantum exposure; it is recorded because an inventory that omits the randomness source is incomplete. `SHA1PRNG` is named explicitly where it appears, since it is a legacy algorithm even though its output is adequate.

This is where the software gets its random numbers. Quantum computers do not weaken it.

What to do. No action. Prefer the platform default over naming an algorithm.

  1. src/peergos/server/crypto/TweetNaCl.java:1261 return new SecureRandom();
  2. src/peergos/server/crypto/asymmetric/mlkem/MlkemSecureRandom.java:32 return new SecureRandom();
  3. src/peergos/server/crypto/hash/lambdaworks/crypto/SCryptUtil.java:45 SecureRandom.getInstance("SHA1PRNG").nextBytes(salt);
  4. src/peergos/server/login/JdbcAccount.java:75 private final SecureRandom rnd = new SecureRandom();
  5. src/peergos/server/net/MountConfigHandler.java:373 new SecureRandom().nextBytes(bytes);
  6. src/peergos/server/storage/FileBlockCache.java:32 private final SecureRandom rnd = new SecureRandom();
  7. src/peergos/server/storage/FileContentAddressedStorage.java:47 private final SecureRandom rnd = new SecureRandom();
  8. src/peergos/server/tests/BackupCodesTest.java:15 test path SecureRandom rnd = new SecureRandom();
  9. src/peergos/server/tests/NitrokeyWebauthn.java:71 test path new SecureRandom().nextBytes(credentialId);
  10. src/peergos/server/tests/StandaloneWebauthnDemo.java:27 test path SecureRandom rnd = new SecureRandom();
  11. src/peergos/server/tests/fips203/FIPS203Tests.java:141 test path SecureRandom.getInstance(SECURE_RANDOM_ALGORITHM).nextBytes(iv);
  12. src/peergos/server/util/Passwords.java:10 SecureRandom rnd = new SecureRandom();
  13. src/peergos/server/webauthn/CtapHid.java:93 new SecureRandom().nextBytes(nonce);
java.rng
scrypt Quantum-safe 5 places See details

Password hashing or key derivation

A `SecretKeyFactory` for PBKDF2, or a BouncyCastle password KDF. Not a quantum exposure, and part of a complete inventory.

This is how passwords are stored. Quantum computers do not meaningfully weaken it.

What to do. PBKDF2 needs a high iteration count. Argon2 through BouncyCastle is stronger.

  1. src/peergos/server/crypto/hash/ScryptJava.java:18 import peergos.server.crypto.hash.lambdaworks.crypto.SCrypt;
  2. src/peergos/server/crypto/hash/ScryptJava.java:46 byte[] scryptHash = SCrypt.scrypt(hash, salt, memoryCost, cpuCost, parallelism, nOutputBytes);
  3. src/peergos/server/crypto/hash/lambdaworks/crypto/SCrypt.java:23 public class SCrypt {
  4. src/peergos/server/crypto/hash/lambdaworks/crypto/SCryptUtil.java:47 byte[] derived = SCrypt.scrypt(passwd.getBytes("UTF-8"), salt, N, r, p, 32);
  5. src/peergos/server/crypto/hash/lambdaworks/crypto/SCryptUtil.java:88 byte[] derived1 = SCrypt.scrypt(passwd.getBytes("UTF-8"), salt, N, r, p, 32);
java.kdf
HMAC Quantum-safe 2 places See details

Message authentication code through the JCA

`Mac.getInstance()`. HMAC is not broken by Shor and is only marginally affected by Grover; it is inventoried, not flagged, unless the underlying digest is broken.

This is a fingerprint used to prove a message was not altered. Quantum computers do not break it.

What to do. No action beyond avoiding HmacMD5 and HmacSHA1.

  1. src/peergos/server/crypto/hash/lambdaworks/crypto/SCrypt.java:86 Mac mac = Mac.getInstance("HmacSHA256");
  2. src/peergos/server/storage/LocalS3Handler.java:421 Mac mac = Mac.getInstance("HmacSHA256");
java.mac
SHA3-512 Quantum-safe 1 place See details

Hash algorithm through the JCA

`MessageDigest.getInstance()`. MD5 and SHA-1 are reported as already broken; SHA-256 is reported as a reduced margin rather than a defect.

No known quantum attack changes how strong this is. No known quantum algorithm changes the security margin.

What to do. SHA-256 as the floor, SHA-384 where the digest protects something that must remain verifiable for decades.

  1. src/peergos/server/crypto/asymmetric/mlkem/fips203/hash/MLKEMHash.java:49 sha3Hash512 = MessageDigest.getInstance("SHA3-512");
java.messagedigest · CWE-328

Cryptographic assets

Algorithm Assessment What it means Occurrences
unknown Could not be determined The algorithm could not be established from the source - chosen at runtime, or decided somewhere this scan does not reach. 59
ML-KEM-768 Quantum-safe No known quantum algorithm changes the security margin. 26
CSPRNG Quantum-safe A cryptographically secure random number generator provided by the platform. Not weakened by a quantum computer. 13
SHA-256 Reduced margin Pre-image resistance falls to about 128 bits of quantum work. Adequate for most uses; SHA-384 restores the full margin where a signature must last decades. 13
scrypt Quantum-safe No known quantum algorithm changes the security margin. 5
MD5 Already broken Practical chosen-prefix collisions exist; MD5 has no remaining security as a digest. 4
TLS Quantum-vulnerable Every TLS cipher suite in general use negotiates a classical key exchange, so a recorded session is decryptable once that exchange falls. 3
HMAC Quantum-safe A keyed MAC is not affected by Shor and only marginally by Grover. 2
Ed25519 Quantum-vulnerable Broken by Shor's algorithm on a cryptographically relevant quantum computer. 2
RSA Quantum-vulnerable Broken by Shor's algorithm on a cryptographically relevant quantum computer. 1
SHA3-256 Reduced margin Grover's algorithm halves the effective strength; the parameter, not the design, is the problem. 1
SHA3-512 Quantum-safe No known quantum algorithm changes the security margin. 1

Imported cryptographic libraries

Library Files
org.bouncycastle — BouncyCastle, whose low-level API bypasses the JCA algorithm strings. It has shipped ML-KEM and ML-DSA since 1.79 1
javax.net.ssl — the TLS client and server 1
javax.crypto — the JCE — ciphers, key agreement and MACs 39