# Cryptographic Algorithms Neo Uses for Digital Signatures and Transaction Validation

> Discover Neo's cryptographic algorithms ECDSA Secp256r1 Ed25519 and BLS12-381 for digital signatures and transaction validation Learn how Neo selects the right algorithm for secure operations.

- Repository: [The Neo Project/neo](https://github.com/neo-project/neo)
- Tags: internals
- Published: 2026-03-08

---

**Neo employs three distinct cryptographic schemes—ECDSA on the Secp256r1 (NIST-P-256) curve, Ed25519, and BLS12-381—to verify digital signatures during transaction validation, selecting the appropriate algorithm based on the witness contract type detected in the transaction payload.**

Understanding the **cryptographic algorithms Neo uses for digital signatures** is essential for developers building secure applications on the neo-project/neo blockchain. Neo's protocol implements a flexible, multi-algorithm architecture that verifies ownership and authorization through distinct cryptographic paths during transaction validation.

## Neo's Cryptographic Algorithm Suite

Neo supports three primary signature algorithms, each optimized for different security and performance characteristics.

### ECDSA Secp256r1 (NIST-P-256)

The default algorithm for standard user accounts and single-signature contracts, **ECDSA on Secp256r1** provides industry-standard elliptic curve cryptography. In [`src/Neo/Cryptography/Crypto.cs`](https://github.com/neo-project/neo/blob/main/src/Neo/Cryptography/Crypto.cs), the `VerifySignature` method validates 64-byte signatures (concatenated `r` and `s` values) against public keys on the `ECCurve.Secp256r1` curve.

This implementation serves as the foundation for most Neo transactions, including standard NEP-17 token transfers and smart contract invocations requiring single-party authorization.

### Ed25519

Used primarily by native contracts such as `CryptoLib`, **Ed25519** offers fast, deterministic signature generation with built-in resistance against side-channel attacks. The implementation resides in [`src/Neo/Cryptography/Ed25519.cs`](https://github.com/neo-project/neo/blob/main/src/Neo/Cryptography/Ed25519.cs) and is exposed to smart contracts through `CryptoLib.VerifyWithEd25519` in [`src/Neo/SmartContract/Native/CryptoLib.cs`](https://github.com/neo-project/neo/blob/main/src/Neo/SmartContract/Native/CryptoLib.cs).

Ed25519 signatures are 64 bytes and utilize the twisted Edwards curve, providing faster verification speeds compared to ECDSA for certain workloads.

### BLS12-381

For advanced use cases requiring **aggregate signatures** and pairing-based cryptography, Neo implements **BLS12-381**. Defined in [`src/Neo/SmartContract/Native/CryptoLib.BLS12_381.cs`](https://github.com/neo-project/neo/blob/main/src/Neo/SmartContract/Native/CryptoLib.BLS12_381.cs), this algorithm allows multiple signatures to be combined into a single short proof.

BLS12-381 supports committee-based consensus scenarios and multi-signature contracts where signature aggregation reduces on-chain storage and verification costs.

## Transaction Validation Architecture

Neo integrates these algorithms into a layered verification pipeline that processes every transaction before inclusion in a block.

### Witness Structure and Contract Detection

Each transaction contains a list of `Witness` objects defined in [`src/Neo/Network/P2P/Payloads/Transaction.cs`](https://github.com/neo-project/neo/blob/main/src/Neo/Network/P2P/Payloads/Transaction.cs). Every witness consists of:

- **Verification script** – The locking script (redeem script) that defines the spending conditions
- **Invocation script** – The unlocking script that provides the actual signatures and parameters

Before selecting a cryptographic algorithm, the engine inspects the verification script using helpers in [`src/Neo/SmartContract/Helper.cs`](https://github.com/neo-project/neo/blob/main/src/Neo/SmartContract/Helper.cs):

```csharp
if (IsSignatureContract(witness.VerificationScript.Span) &&
    IsSingleSignatureInvocationScript(witness.InvocationScript, out var signature))
{
    // Route to single-signature ECDSA verification
}
else if (IsMultiSigContract(witness.VerificationScript.Span))
{
    // Route to multi-signature verification logic
}

```

### Single-Signature Verification Flow

For standard single-signature contracts, the validation process follows this sequence:

1. **Public key extraction** – The engine recovers the public key from the contract's redeem script using `Contract.CreateSignatureRedeemScript(pubkey)` found in [`src/Neo/SmartContract/Contract.cs`](https://github.com/neo-project/neo/blob/main/src/Neo/SmartContract/Contract.cs).

2. **Sign data calculation** – The transaction hash is computed via `ScriptContainer.GetSignData(network)`, referenced in [`ApplicationEngine.Crypto.cs`](https://github.com/neo-project/neo/blob/main/ApplicationEngine.Crypto.cs).

3. **Signature verification** – The system calls `Crypto.VerifySignature` with the Secp256r1 curve:

```csharp
if (!Crypto.VerifySignature(this.GetSignData(settings.Network),
                           signature.Span,
                           pubkey,
                           ECCurve.Secp256r1))
    return VerifyResult.InvalidSignature;

```

### Multi-Signature and Native Contract Verification

**Multi-signature contracts** extract all public keys from the redeem script, then iterate through provided signatures, verifying each against the transaction hash using the same `Crypto.VerifySignature` routine.

**Ed25519 verification** occurs when native contracts require this specific scheme. The engine delegates to:

```csharp
CryptoLib.VerifyWithEd25519(message, pubkey, signature);

```

**BLS12-381 aggregate signatures** are validated through [`CryptoLib.BLS12_381.cs`](https://github.com/neo-project/neo/blob/main/CryptoLib.BLS12_381.cs), where `VerifyBlsSignature` performs pairing-based cryptographic checks to confirm that aggregated signatures correspond to the claimed set of public keys.

## Practical Implementation Examples

### Signing with ECDSA Secp256r1

Standard user transactions utilize the `KeyPair` class in [`src/Neo/Wallets/KeyPair.cs`](https://github.com/neo-project/neo/blob/main/src/Neo/Wallets/KeyPair.cs) to generate signatures:

```csharp
using Neo.Cryptography;
using Neo.Wallets;

// Generate Secp256r1 key pair
var keyPair = new KeyPair(privateKeyBytes);
byte[] message = System.Text.Encoding.UTF8.GetBytes("Neo transaction data");

// Create 64-byte signature (r || s)
byte[] signature = keyPair.Sign(message);

// Verify using static Crypto class
bool isValid = Crypto.VerifySignature(message, signature, keyPair.PublicKey, ECCurve.Secp256r1);

```

### Creating Single-Signature Contracts

To lock funds to a specific public key, developers use `Contract.CreateSignatureRedeemScript`:

```csharp
using Neo.SmartContract;
using Neo.Cryptography.ECC;

// Decode public key from bytes
ECPoint publicKey = ECPoint.DecodePoint(pubKeyBytes, ECCurve.Secp256r1);

// Generate the verification script
byte[] redeemScript = Contract.CreateSignatureRedeemScript(publicKey);

// Create contract object
var contract = new Contract
{
    Script = redeemScript,
    ParameterList = new[] { ContractParameterType.Signature }
};

```

During transaction validation, Neo extracts the public key from this script and verifies the provided signature against it.

### Verifying Ed25519 Signatures

For contracts requiring Ed25519, native code paths invoke the specialized verifier:

```csharp
using Neo.SmartContract.Native;

// message, pubKey (32 bytes), signature (64 bytes)
bool valid = CryptoLib.VerifyWithEd25519(messageBytes, ed25519PubKey, ed25519Signature);

```

### BLS12-381 Aggregate Verification

Committee-based operations utilize BLS aggregation for efficiency:

```csharp
// Verify aggregated signature against multiple public keys
bool result = CryptoLib.VerifyBlsAggregateSignature(
    messageHash, 
    publicKeyG1Points, 
    aggregateSignatureG2
);

```

## Summary

- Neo supports **three cryptographic algorithms** for digital signatures: ECDSA Secp256r1 (default), Ed25519 (native contracts), and BLS12-381 (aggregate signatures).
- Transaction validation relies on a **Witness structure** containing verification and invocation scripts, parsed by helper functions in [`Helper.cs`](https://github.com/neo-project/neo/blob/main/Helper.cs).
- The engine automatically **detects contract types** (`IsSignatureContract`, `IsMultiSigContract`) to route validation through the appropriate cryptographic primitive.
- **ECDSA verification** uses `Crypto.VerifySignature` in [`Crypto.cs`](https://github.com/neo-project/neo/blob/main/Crypto.cs), while **Ed25519 and BLS** operations are handled through the native `CryptoLib` contract.

## Frequently Asked Questions

### Which cryptographic curve does Neo use by default for standard user transactions?

Neo defaults to **ECDSA on the Secp256r1 curve** (also known as NIST-P-256) for standard user accounts and single-signature contracts. This implementation resides in [`src/Neo/Cryptography/Crypto.cs`](https://github.com/neo-project/neo/blob/main/src/Neo/Cryptography/Crypto.cs) and produces 64-byte signatures consisting of the concatenated `r` and `s` values.

### How does Neo handle multi-signature transaction validation?

Neo detects multi-signature contracts using `IsMultiSigContract` in [`src/Neo/SmartContract/Helper.cs`](https://github.com/neo-project/neo/blob/main/src/Neo/SmartContract/Helper.cs). The engine extracts all public keys embedded in the redeem script, then iterates through the signatures provided in the invocation script, verifying each against the transaction hash using `Crypto.VerifySignature` until the required threshold of valid signatures is met.

### What is the role of the CryptoLib native contract in Neo's signature validation?

`CryptoLib` in [`src/Neo/SmartContract/Native/CryptoLib.cs`](https://github.com/neo-project/neo/blob/main/src/Neo/SmartContract/Native/CryptoLib.cs) exposes advanced cryptographic primitives—including Ed25519 verification via `VerifyWithEd25519` and BLS12-381 operations via [`CryptoLib.BLS12_381.cs`](https://github.com/neo-project/neo/blob/main/CryptoLib.BLS12_381.cs)—that standard smart contracts cannot access directly. This native contract enables deterministic Ed25519 validation and pairing-based BLS signature aggregation for committee and group signature scenarios.

### Where is the transaction signature hash calculated in the Neo source code?

The transaction hash used for signature verification is calculated by `GetSignData(network)` defined in the transaction payload implementation ([`src/Neo/Network/P2P/Payloads/Transaction.cs`](https://github.com/neo-project/neo/blob/main/src/Neo/Network/P2P/Payloads/Transaction.cs)). This method produces the exact byte sequence that signers must hash and sign to prove transaction authorization.