Crypto API Reference

← Crypto Main


CryptoOps

Main interface providing platform-specific cryptographic operations. Provides the same API on both JVM and JavaScript.

keccak256

def keccak256(input: Array[Byte]): Array[Byte]

Computes Keccak-256 hash of input bytes.

Parameters:

Returns:

Features:

Example:

val message = "Hello, World!".getBytes
val hash = CryptoOps.keccak256(message)
assert(hash.length == 32)

generate

def generate(): KeyPair

Generates a new random secp256k1 key pair.

Returns:

Features:

Example:

val keyPair1 = CryptoOps.generate()
val keyPair2 = CryptoOps.generate()
assert(keyPair1.privateKey != keyPair2.privateKey)

fromPrivate

def fromPrivate(privateKey: BigInt): KeyPair

Derives a key pair from an existing private key.

Parameters:

Returns:

Features:

Example:

import org.sigilaris.core.datatype.UInt256

val privateKey = UInt256.fromHex("0123456789abcdef...").toOption.get
val keyPair = CryptoOps.fromPrivate(privateKey.toBigInt)

sign

def sign(keyPair: KeyPair, transactionHash: Array[Byte]): Either[SigilarisFailure, Signature]

Signs a message hash with ECDSA.

Parameters:

Returns:

Features:

Example:

val keyPair = CryptoOps.generate()
val message = "Sign this!".getBytes
val hash = CryptoOps.keccak256(message)

CryptoOps.sign(keyPair, hash) match {
  case Right(signature) => println(s"Signed: $signature")
  case Left(error) => println(s"Error: $error")
}

recover

def recover(signature: Signature, hashArray: Array[Byte]): Either[SigilarisFailure, PublicKey]

Recovers public key from signature and message hash.

Parameters:

Returns:

Features:

Example:

val keyPair = CryptoOps.generate()
val hash = CryptoOps.keccak256("message".getBytes)
val signature = CryptoOps.sign(keyPair, hash).toOption.get

CryptoOps.recover(signature, hash) match {
  case Right(publicKey) =>
    assert(publicKey == keyPair.publicKey)
  case Left(error) =>
    println(s"Recovery failed: $error")
}

KeyPair

Data type representing a secp256k1 key pair.

final case class KeyPair(privateKey: UInt256, publicKey: PublicKey)

Fields:

Example:

val keyPair = CryptoOps.generate()
println(s"Private: ${keyPair.privateKey}")
println(s"Public: ${keyPair.publicKey}")

Related Functions:


Signature

ECDSA signature with recovery parameter for secp256k1.

final case class Signature(v: Int, r: UInt256, s: UInt256)

Fields:

Low-S Normalization: Signatures are automatically normalized to Low-S form to prevent signature malleability.

Example:

val signature = Signature(
  v = 27,
  r = UInt256.fromHex("...").toOption.get,
  s = UInt256.fromHex("...").toOption.get
)

Related Functions:


Hash

Type class for type-safe Keccak-256 hashing.

trait Hash[A]:
  def apply(a: A): Hash.Value[A]
  def contramap[B](f: B => A): Hash[B]

Hash.Value

Opaque type wrapping UInt256 to track the source type of the hash.

opaque type Value[A] = UInt256

Type Parameter:

Creating Hash Instances

build

def build[A: ByteEncoder]: Hash[A]

Builds a Hash instance for any type with a ByteEncoder.

Example:

import org.sigilaris.core.codec.byte.ByteEncoder

case class User(id: Long, name: String)

given Hash[User] = Hash.build[User]

val user = User(1L, "Alice")
val userHash = user.toHash

Extension Methods

extension [A](a: A) def toHash(using h: Hash[A]): Hash.Value[A]
extension [A](value: Hash.Value[A]) def toUInt256: UInt256

Example:

import org.sigilaris.core.crypto.Hash.ops.*
import org.sigilaris.core.datatype.Utf8

val utf8 = Utf8("hello")
val hash: Hash.Value[Utf8] = utf8.toHash
val uint256: UInt256 = hash.toUInt256

Default Instances

Utf8

given Hash[Utf8] = Hash.build

Default Hash instance for UTF-8 strings.

Example:

import org.sigilaris.core.datatype.Utf8

val text = Utf8("Hello, World!")
val hash = text.toHash

PublicKey

Represents a secp256k1 public key. May have different implementations on different platforms but provides the same API.

Types

PublicKey is implemented as a sealed trait with two possible forms:

  1. XY: Byte-oriented representation (x, y coordinates)
  2. Point: Elliptic curve point-oriented representation (JVM only, performance optimized)

Representation

Features

Example:

val keyPair = CryptoOps.generate()
val publicKey = keyPair.publicKey

// Public key can be serialized to 64 bytes
val bytes = publicKey.toBytes
assert(bytes.length == 64)

Error Handling

Cryptographic operations can fail and return Either[SigilarisFailure, A].

Common Errors

Signature Creation:

Public Key Recovery:

Example:

val result = CryptoOps.sign(keyPair, hash)
result match {
  case Right(signature) =>
    // Use signature
    println(s"Success: $signature")
  case Left(error) =>
    // Handle error
    println(s"Failed: ${error.message}")
}

Usage Tips

1. Hash Reuse

Don't hash the same message multiple times:

// Bad
val hash1 = CryptoOps.keccak256(message)
val hash2 = CryptoOps.keccak256(message)

// Good
val hash = CryptoOps.keccak256(message)
// Reuse hash multiple times

2. Type-Safe Hashing

Use the Hash type class to preserve type information:

import org.sigilaris.core.crypto.Hash.ops.*

case class Document(content: String)
given Hash[Document] = Hash.build[Document]

val doc = Document("important")
val docHash: Hash.Value[Document] = doc.toHash

3. Error Handling

Always handle the failure case of Either:

for {
  signature <- CryptoOps.sign(keyPair, hash)
  publicKey <- CryptoOps.recover(signature, hash)
} yield {
  // Success path
  println(s"Recovered: $publicKey")
}

← Crypto Main