public static Signature ReadSignature(this BinaryReader reader) { var kind = (SignatureKind)reader.ReadByte(); switch (kind) { case SignatureKind.None: return(null); case SignatureKind.Ed25519: { var signature = new Ed25519Signature(); signature.UnserializeData(reader); return(signature); } case SignatureKind.Ring: { var signature = new RingSignature(); signature.UnserializeData(reader); return(signature); } default: throw new NotImplementedException("read signature: " + kind); } }
public RingSignature[] Sign(byte[] msg, byte[] keyImage, IKey[] publicKeys, byte[] secretKey, int index) { RingSignature[] signatures = new RingSignature[publicKeys.Length]; byte[][] pubs = publicKeys.Select(pk => pk.Value.ToArray()).ToArray(); GroupOperations.ge_frombytes(out GroupElementP3 keyImageP3, keyImage, 0); GroupElementCached[] image_pre = new GroupElementCached[8]; GroupOperations.ge_dsm_precomp(image_pre, ref keyImageP3); byte[] sum = new byte[32], k = null, h = null; IHash hasher = HashFactory.Crypto.SHA3.CreateKeccak256(); hasher.TransformBytes(msg); for (int i = 0; i < publicKeys.Length; i++) { signatures[i] = new RingSignature(); if (i == index) { k = GetRandomSeed(true); GroupOperations.ge_scalarmult_base(out GroupElementP3 tmp3, k, 0); byte[] tmp3bytes = new byte[32]; GroupOperations.ge_p3_tobytes(tmp3bytes, 0, ref tmp3); hasher.TransformBytes(tmp3bytes); tmp3 = Hash2Point(pubs[i]); GroupOperations.ge_scalarmult(out GroupElementP2 tmp2, k, ref tmp3); byte[] tmp2bytes = new byte[32]; GroupOperations.ge_tobytes(tmp2bytes, 0, ref tmp2); hasher.TransformBytes(tmp2bytes); } else { signatures[i].C = GetRandomSeed(true); signatures[i].R = GetRandomSeed(true); GroupOperations.ge_frombytes(out GroupElementP3 tmp3, pubs[i], 0); GroupOperations.ge_double_scalarmult_vartime(out GroupElementP2 tmp2, signatures[i].C, ref tmp3, signatures[i].R); byte[] tmp2bytes = new byte[32]; GroupOperations.ge_tobytes(tmp2bytes, 0, ref tmp2); hasher.TransformBytes(tmp2bytes); tmp3 = Hash2Point(pubs[i]); GroupOperations.ge_double_scalarmult_precomp_vartime(out tmp2, signatures[i].R, tmp3, signatures[i].C, image_pre); tmp2bytes = new byte[32]; GroupOperations.ge_tobytes(tmp2bytes, 0, ref tmp2); hasher.TransformBytes(tmp2bytes); ScalarOperations.sc_add(sum, sum, signatures[i].C); } } h = hasher.TransformFinal().GetBytes(); ScalarOperations.sc_sub(signatures[index].C, h, sum); ScalarOperations.sc_reduce32(signatures[index].C); ScalarOperations.sc_mulsub(signatures[index].R, signatures[index].C, secretKey, k); ScalarOperations.sc_reduce32(signatures[index].R); return(signatures); }
public void RingSignatures() { var rand = new Random(); int participants = 5; var messages = new[] { "hello", "phantasma chain", "welcome to the future" }.Select(Encoding.UTF8.GetBytes).ToArray(); var keys = Enumerable.Range(0, participants).Select(i => RingSignature.GenerateKeyPair(PhantasmaKeys.Generate())).ToArray(); foreach (var key in keys) { Assert.IsTrue(BigInteger.ModPow(RingSignature.GroupParameters.Generator, key.PrivateKey, RingSignature.GroupParameters.Prime) == key.PublicKey); } var publicKeys = keys.Select(k => k.PublicKey).ToArray(); var signatures = new RingSignature[participants, messages.Length]; for (int i = 0; i < participants; ++i) { for (int j = 0; j < messages.Length; ++j) { signatures[i, j] = RingSignature.GenerateSignature(messages[j], publicKeys, keys[i].PrivateKey, i); Assert.IsTrue(signatures[i, j].VerifySignature(messages[j], publicKeys)); for (int k = 0; k < messages.Length; ++k) { Assert.IsFalse(signatures[i, j].VerifySignature(messages[k], publicKeys) != (k == j)); } var orig = signatures[i, j]; var tampered = new RingSignature(orig.Y0, orig.S.FlipBit(rand.Next(orig.S.GetBitLength())), orig.C); Assert.IsFalse(tampered.VerifySignature(messages[j], publicKeys)); tampered = new RingSignature(orig.Y0.FlipBit(rand.Next(orig.Y0.GetBitLength())), orig.S, orig.C); Assert.IsFalse(tampered.VerifySignature(messages[j], publicKeys)); var s = (BigInteger[])orig.C.Clone(); var t = rand.Next(s.Length); s[t] = s[t].FlipBit(rand.Next(s[t].GetBitLength())); tampered = new RingSignature(orig.Y0, orig.S, s); Assert.IsFalse(tampered.VerifySignature(messages[j], publicKeys)); } } for (int i = 0; i < participants; ++i) { for (int j = 0; j < messages.Length; ++j) { for (int k = 0; k < participants; ++k) { for (int l = 0; l < messages.Length; ++l) { Assert.IsTrue(signatures[i, j].IsLinked(signatures[k, l]) == (i == k)); } } } } }
private void btnGenRingSig_Click(object sender, RoutedEventArgs e) { using (RingSigKeys[0].Decrypt()) { IEnumerable <Pure.Cryptography.ECC.ECPoint> pubKeys = RingSigKeys.Select(p => p.PublicKey); RingSignature sign = message.RingSign(pubKeys.ToList(), RingSigKeys[0].PrivateKey, keyImage.ToByteArray().Reverse().ToArray(), 0); sign.RingVerify(message, pubKeys.ToList()); } }
protected override PacketBase ParseBlockBase(ushort version, Memory <byte> spanBody, out Memory <byte> spanPostBody) { int readBytes = 0; byte[] destinationKey = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; byte[] destinationKey2 = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; byte[] transactionPublicKey = spanBody.Slice(readBytes, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytes += Globals.NODE_PUBLIC_KEY_SIZE; spanPostBody = ParseUtxoConfidential(version, spanBody.Slice(readBytes), out UtxoConfidentialBase utxoConfidentialBase); ushort readBytesPostBody = 0; Memory <byte> keyImage = spanPostBody.Slice(readBytesPostBody, Globals.NODE_PUBLIC_KEY_SIZE); readBytesPostBody += Globals.NODE_PUBLIC_KEY_SIZE; ushort ringSignaturesCount = BinaryPrimitives.ReadUInt16LittleEndian(spanPostBody.Span.Slice(readBytesPostBody)); readBytesPostBody += sizeof(ushort); utxoConfidentialBase.KeyImage = _entityIdentityKeyProvider.GetKey(keyImage); utxoConfidentialBase.DestinationKey = destinationKey; utxoConfidentialBase.DestinationKey2 = destinationKey2; utxoConfidentialBase.TransactionPublicKey = transactionPublicKey; utxoConfidentialBase.PublicKeys = new IKey[ringSignaturesCount]; utxoConfidentialBase.Signatures = new RingSignature[ringSignaturesCount]; for (int i = 0; i < ringSignaturesCount; i++) { byte[] publicKey = spanPostBody.Slice(readBytesPostBody, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); IKey key = _entityIdentityKeyProvider.GetKey(spanPostBody.Slice(readBytesPostBody, Globals.NODE_PUBLIC_KEY_SIZE)); utxoConfidentialBase.PublicKeys[i] = key; readBytesPostBody += Globals.NODE_PUBLIC_KEY_SIZE; } for (int i = 0; i < ringSignaturesCount; i++) { byte[] c = spanPostBody.Slice(readBytesPostBody, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytesPostBody += Globals.NODE_PUBLIC_KEY_SIZE; byte[] r = spanPostBody.Slice(readBytesPostBody, Globals.NODE_PUBLIC_KEY_SIZE).ToArray(); readBytesPostBody += Globals.NODE_PUBLIC_KEY_SIZE; RingSignature ringSignature = new RingSignature { C = c, R = r }; utxoConfidentialBase.Signatures[i] = ringSignature; } spanPostBody = spanPostBody.Slice(readBytesPostBody); return(utxoConfidentialBase); }
public static bool RingVerify(this RingSignature signature, byte[] message, List <Cryptography.ECC.ECPoint> pubKeys) { #region Calculate L{i} & R{i} List <byte[]> L = new List <byte[]>(); List <byte[]> R = new List <byte[]>(); for (int i = 0; i < RingSignature.RING_SIZE; i++) { byte[] L_i = (Cryptography.ECC.ECCurve.Secp256r1.G * signature.R[i] + pubKeys[i] * signature.C[i]).ToString().HexToBytes(); L.Add(L_i); BigInteger R_i = ((new BigInteger(signature.R[i].Reverse().Concat(new byte[1]).ToArray()) * new BigInteger(Crypto.Default.Hash256(pubKeys[i].ToString().HexToBytes()).Reverse().Concat(new byte[1]).ToArray())) + (new BigInteger(signature.C[i].Reverse().Concat(new byte[1]).ToArray()) * new BigInteger(signature.KeyImage.Reverse().Concat(new byte[1]).ToArray())).Mod(Cryptography.ECC.ECCurve.Secp256r1.N)).Mod(Cryptography.ECC.ECCurve.Secp256r1.N); R.Add(R_i.ToByteArray().Reverse().ToArray()); } #endregion #region Calculate Sigma C{i} BigInteger SigmaC = BigInteger.Zero; for (int i = 0; i < RingSignature.RING_SIZE; i++) { SigmaC += new BigInteger(signature.C[i].Reverse().Concat(new byte[1]).ToArray()); } SigmaC = SigmaC.Mod(Cryptography.ECC.ECCurve.Secp256r1.N); #endregion #region Calcuate Hash int totalSize = message.Length + L.Select(p => p.Length).Sum() + R.Select(p => p.Length).Sum(); byte[] data = new byte[totalSize]; int dstOff = 0; Buffer.BlockCopy(message, 0, data, dstOff, message.Length); dstOff += message.Length; for (int i = 0; i < RingSignature.RING_SIZE; i++) { Buffer.BlockCopy(L[i], 0, data, dstOff, L[i].Length); dstOff += L[i].Length; } for (int i = 0; i < RingSignature.RING_SIZE; i++) { Buffer.BlockCopy(R[i], 0, data, dstOff, R[i].Length); dstOff += R[i].Length; } byte[] c = Crypto.Default.Hash256(data); BigInteger iC = (new BigInteger(c.Reverse().Concat(new byte[1]).ToArray())).Mod(Cryptography.ECC.ECCurve.Secp256r1.N); #endregion if (SigmaC != iC) { return(false); } return(true); }
public void TakePrivate(Address to, string symbol, uint queueID, RingSignature signature) { Runtime.Expect(Runtime.Nexus.TokenExists(symbol), "invalid token"); var tokenInfo = this.Runtime.Nexus.GetTokenInfo(symbol); Runtime.Expect(tokenInfo.Flags.HasFlag(TokenFlags.Fungible), "token must be fungible"); var queue = FindQueue(symbol, queueID); Runtime.Expect(queue.ID > 0, "invalid queue"); Runtime.Expect(queue.ID == queueID, "mismatching queue"); Runtime.Expect(queue.addresses.Count() == queue.size, "queue not full yet"); var addresses = queue.addresses.All <Address>(); foreach (var address in addresses) { Runtime.Expect(address != to, "cant send to anyone already in the queue"); } var msg = this.Runtime.Transaction.ToByteArray(false); Runtime.Expect(signature.Verify(msg, addresses), "ring signature failed"); var signatures = queue.signatures.All <Signature>(); foreach (RingSignature otherSignature in signatures) { Runtime.Expect(!signature.IsLinked(otherSignature), "ring signature already linked"); } queue.signatures.Add(signature); // TODO this is wrong var balances = new BalanceSheet(symbol); balances.Add(this.Storage, to, TransferAmount); }