// mimic of VerifySignatureHashed of DefaultCrypto.cs but using different chain id public bool VerifySignatureHashed(byte[] messageHash, byte[] signature, byte[] publicKey, bool useNewChainId) { if (messageHash.Length != 32 || signature.Length != SignatureSize(useNewChainId)) { return(false); } return(EcVerify.Benchmark(() => { var pk = new byte[64]; if (!Secp256K1.PublicKeyParse(pk, publicKey)) { return false; } var publicKeySerialized = new byte[33]; if (!Secp256K1.PublicKeySerialize(publicKeySerialized, pk, Flags.SECP256K1_EC_COMPRESSED)) { throw new Exception("Cannot serialize parsed key: how did it happen?"); } var parsedSig = new byte[65]; var recId = (RestoreEncodedRecIdFromSignatureBuffer(signature) - 36) / 2 / ChainId(useNewChainId); if (recId < 0 || recId > 3) { throw new Exception($"Invalid recId={recId}: : recId >= 0 && recId <= 3 "); } if (!Secp256K1.RecoverableSignatureParseCompact(parsedSig, signature.Take(64).ToArray(), recId)) { return false; } return Secp256K1.Verify(parsedSig.Take(64).ToArray(), messageHash, pk); })); }
public bool AddShare(int idx, Signature sigShare, out Signature?result) { result = null; if (idx < 0 || idx >= _publicKeySet.Count) { Logger.LogWarning($"Public key (?) is not recognized (index {idx})"); return(false); } var pubKey = _publicKeySet[idx]; if (_collectedShares[idx] != null) { Logger.LogWarning($"Signature share {idx} input twice"); if (sigShare != _collectedShares[idx]) { return(false); } _collectedSharesNumber--; // to compensate increment later } if (!IsShareValid(pubKey, sigShare)) { Logger.LogWarning($"Signature share {idx} is not valid: {sigShare.ToHex()}"); return(false); } if (_collectedSharesNumber > _publicKeySet.Threshold) { result = _signature; return(true); } Logger.LogTrace($"Collected signature share #{idx}: {sigShare.RawSignature.ToHex()}"); _collectedShares[idx] = sigShare; _collectedSharesNumber += 1; if (_collectedSharesNumber <= _publicKeySet.Threshold) { return(true); } var signature = CombineBenchmark.Benchmark(() => _publicKeySet.AssembleSignature( _collectedShares.Select((share, i) => new KeyValuePair <int, Signature>(i, share)) .Where(pair => pair.Value != null).ToArray() )); if (!_publicKeySet.SharedPublicKey.ValidateSignature(signature, _dataToSign)) { throw new Exception("Fatal error: all shares are valid but combined signature is not"); } _signature = signature; result = signature; return(true); }
public PartiallyDecryptedShare Decrypt(EncryptedShare share) { return(DecryptBenchmark.Benchmark(() => { var h = Utils.HashToG2(share.U, share.V); if (!GT.Pairing(G1.Generator, share.W).Equals(GT.Pairing(share.U, h))) { throw new Exception("Invalid share!"); } var ui = share.U * _x; return new PartiallyDecryptedShare(ui, _id, share.Id); })); }
public EncryptedShare Encrypt(IRawShare rawShare) { return(EncryptBenchmark.Benchmark(() => { var r = Fr.GetRandom(); var u = G1.Generator * r; var shareBytes = rawShare.ToBytes(); var t = _y * r; var v = Utils.XorWithHash(t, shareBytes); var w = Utils.HashToG2(u, v) * r; return new EncryptedShare(u, v, w, rawShare.Id); })); }
public byte[] RecoverSignatureHashed(byte[] messageHash, byte[] signature, bool useNewChainId) { if (messageHash.Length != 32) { throw new ArgumentException(nameof(messageHash)); } if (signature.Length != SignatureSize(useNewChainId)) { throw new ArgumentException(nameof(signature)); } return(EcRecover.Benchmark(() => { var parsedSig = new byte[65]; var pk = new byte[64]; var encodedRecId = RestoreEncodedRecIdFromSignatureBuffer(signature); var recId = (encodedRecId - 36) / 2 / TransactionUtils.ChainId(useNewChainId); if (recId < 0 || recId > 3) { throw new Exception($"Invalid recId={recId}: : recId >= 0 && recId <= 3 "); } if (!Secp256K1.RecoverableSignatureParseCompact(parsedSig, signature.Take(64).ToArray(), recId)) { throw new ArgumentException(nameof(signature)); } if (!Secp256K1.Recover(pk, parsedSig, messageHash)) { throw new ArgumentException("Bad signature"); } var result = new byte[33]; if (!Secp256K1.PublicKeySerialize(result, pk, Flags.SECP256K1_EC_COMPRESSED)) { throw new Exception("Cannot serialize recovered public key: how did it happen?"); } return result; })); }
public RawShare FullDecrypt(EncryptedShare share, List <PartiallyDecryptedShare> us) { return(FullDecryptBenchmark.Benchmark(() => { if (us.Count < _t) { throw new Exception("Insufficient number of shares!"); } var ids = new HashSet <int>(); foreach (var part in us) { if (ids.Contains(part.DecryptorId)) { throw new Exception($"Id {part.DecryptorId} was provided more than once!"); } if (part.ShareId != share.Id) { throw new Exception($"Share id mismatch for decryptor {part.DecryptorId}"); } ids.Add(part.DecryptorId); } var ys = new List <G1>(); var xs = new List <Fr>(); foreach (var part in us) { xs.Add(Fr.FromInt(part.DecryptorId + 1)); ys.Add(part.Ui); } var u = MclBls12381.LagrangeInterpolate(xs.ToArray(), ys.ToArray()); return new RawShare(Utils.XorWithHash(u, share.V), share.Id); })); }
private bool IsShareValid(PublicKey pubKey, Signature sigShare) { return(VerifyBenchmark.Benchmark(() => pubKey.ValidateSignature(sigShare, _dataToSign))); }
public Signature Sign() { return(SignBenchmark.Benchmark(() => _privateKeyShare.HashAndSign(_dataToSign))); }