diff --git a/src/main/java/com/sparrowwallet/drongo/wallet/SeedQR.java b/src/main/java/com/sparrowwallet/drongo/wallet/SeedQR.java new file mode 100644 index 0000000..30231cd --- /dev/null +++ b/src/main/java/com/sparrowwallet/drongo/wallet/SeedQR.java @@ -0,0 +1,58 @@ +package com.sparrowwallet.drongo.wallet; + +import com.sparrowwallet.drongo.Utils; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class SeedQR { + public static DeterministicSeed getSeed(String seedQr) { + if(seedQr.length() < 48 || seedQr.length() > 96 || seedQr.length() % 4 > 0) { + throw new IllegalArgumentException("Invalid SeedQR length: " + seedQr.length()); + } + + if(!seedQr.chars().allMatch(c -> c >= '0' && c <= '9')) { + throw new IllegalArgumentException("SeedQR contains non-digit characters: " + seedQr); + } + + List indexes = IntStream.iterate(0, i -> i + 4).limit((int)Math.ceil(seedQr.length() / 4.0)) + .mapToObj(i -> seedQr.substring(i, Math.min(i + 4, seedQr.length()))) + .map(Integer::parseInt) + .collect(Collectors.toList()); + + List words = new ArrayList<>(indexes.size()); + for(Integer index : indexes) { + words.add(Bip39MnemonicCode.INSTANCE.getWordList().get(index)); + } + + return new DeterministicSeed(words, null, System.currentTimeMillis(), DeterministicSeed.Type.BIP39); + } + + public static DeterministicSeed getSeed(byte[] compactSeedQr) { + if(compactSeedQr[0] != 0x41 && compactSeedQr[0] != 0x42) { + throw new IllegalArgumentException("Invalid CompactSeedQR header"); + } + + if(compactSeedQr.length < 19) { + throw new IllegalArgumentException("Invalid CompactSeedQR length"); + } + + String qrHex = Utils.bytesToHex(compactSeedQr); + String seedHex; + if(qrHex.endsWith("0ec")) { + seedHex = qrHex.substring(3, qrHex.length() - 3); + } else { + seedHex = qrHex.substring(3, qrHex.length() - 1); + } + + byte[] seed = Utils.hexToBytes(seedHex); + + if(seed.length < 16 || seed.length > 32 || seed.length % 4 > 0) { + throw new IllegalArgumentException("Invalid CompactSeedQR length: " + compactSeedQr.length); + } + + return new DeterministicSeed(seed, null, System.currentTimeMillis()); + } +}