Skip to main content
Pourya Bagheri
Quantum Computing | Blockchain Soloution | MERN
View all authors

Building a Full-Stack Application with Wasp Integrating Server and Front-End Components

· 4 min read
Pourya Bagheri
Quantum Computing | Blockchain Soloution | MERN

Wasp is a modern, declarative language that enables developers to rapidly build full-stack web applications. By abstracting the complexities of setting up both the server and the client, Wasp lets you focus on your application’s logic and design. In this article, we’ll walk through creating a simple full-stack app that includes a server API endpoint and a front-end that fetches and displays data from that endpoint.

Application Overview

Our example application, MyFullStackApp, demonstrates how to:

  • Define the overall app configuration.
  • Set up a routing structure for navigation.
  • Build a React-based front-end component.
  • Create a server endpoint that responds with a greeting message.

The complete code example is shown below.

Code Example


app MyFullStackApp {
title: "My Full-Stack Wasp App"
description: "A full-stack application example built with Wasp that integrates server and front-end components."
}

route HomeRoute {
path: "/"
component: HomePage
}

page HomePage {
component: HomePageComponent
}

component HomePageComponent {
<div>
<h1>Welcome to My Full-Stack Wasp App!</h1>
<p>This example demonstrates how to connect your front-end with a server API.</p>
<GreetingComponent/>
</div>
}

component GreetingComponent {
<script>
import React, { useEffect, useState } from 'react';

function GreetingComponent() {
const [greeting, setGreeting] = useState("");

useEffect(() => {
fetch("/api/greeting")
.then(response => response.json())
.then(data => setGreeting(data.greeting))
.catch(error => console.error("Error fetching greeting:", error));
}, []);

return (
<div>
<p>{greeting ? greeting : "Loading greeting..."}</p>
</div>
);
}

export default GreetingComponent;
</script>
}

server getGreeting {
handler: function(req, res) {
// Respond with a greeting message in JSON format
res.json({ greeting: "Hello from the server!" });
},
method: "GET",
path: "/api/greeting"
}

Detailed Explanation

1. Application Setup

  • App Definition:

    The app block defines the general configuration for the application, such as its title and description. This acts as a central declaration point for your project.

  • Routing:

    The route HomeRoute block maps the root path ("/") to the HomePage page. This structure makes it easy to manage navigation within the app.

2. Front-End Components

  • Page and Component Structure:

    The HomePage page is linked to the HomePageComponent, which composes the visible UI elements. Within this component, a header and a brief description are provided, along with the inclusion of the GreetingComponent.

  • GreetingComponent:

    This is a React component embedded within a Wasp component. The component uses React’s hooks:

    • useState: Initializes the greeting state variable.
    • useEffect: Performs a fetch request to the server endpoint /api/greeting when the component mounts.

The fetched greeting is then displayed on the page. Error handling is also included to log any issues during the fetch operation.

3. Server-Side Code

  • Server Endpoint:

    The server getGreeting block defines an API endpoint:

    • handler: A function that sends a JSON response with a greeting message.

    • method: The HTTP method (GET) used to access this endpoint.

    • path: The URL path (/api/greeting) where the server listens for requests.

This server code demonstrates a typical pattern of exposing backend functionality via a RESTful API, which the front-end can consume.

4. Integration of Server and Front-End

  • Data Flow:

    When a user visits the homepage, the HomePageComponent renders and includes the GreetingComponent. On mounting, the GreetingComponent makes a GET request to the /api/greeting endpoint. The server responds with a JSON payload containing the greeting, which is then rendered in the UI. This seamless integration between server and client is one of Wasp’s strengths.

  • Declarative Structure:

    Wasp’s declarative syntax helps keep the code organized. Developers can easily see how the app is structured, which routes lead to which pages, and how components are interconnected with server actions.

How to Install, Run, and Deploy a Wasp Application

1. Prerequisites

Before you begin, make sure you have the following installed on your system:

  • Node.js and npm:

Verify the installation with these commands:

node -v
npm -v

2. Installing Wasp CLI

Method 1: Using curl

curl -L https://get.wasp-lang.dev | sh

Method 2: Using npm

npm install -g wasp-lang

3. Creating a New Project

Once the Wasp CLI is installed, you can create a new project by running:

Create a New Project:

wasp new my-fullstack-app

Navigate to the Project Directory:

cd my-fullstack-app

4. Running the Application in Development Mode

wasp start

5. Building the Production Version

When you are ready to deploy your app for end users, you need to create a production build:

wasp build

6. Deploying the Application

Deploying with Docker

FROM node:14
WORKDIR /app
COPY . .
RUN npm install
RUN wasp build
CMD ["npm", "start"]

Build the Docker Image:

docker build -t my-fullstack-app .

Run the Docker Container:

docker run -p 3000:3000 my-fullstack-app

A Comprehensive Guide to Launching n8n.io for Workflow Automation

· 3 min read
Pourya Bagheri
Quantum Computing | Blockchain Soloution | MERN

In today’s fast-paced digital world, automation is no longer a luxury—it’s a necessity. n8n.io is an open-source workflow automation tool that enables you to automate repetitive tasks, integrate various services, and streamline your operations with minimal coding. This guide will walk you through everything you need to know to get started with n8n, from understanding its benefits to launching and configuring your instance.

Fair-code workflow automation platform with native AI capabilities.
Combine visual building with
custom code, self-host or cloud, 400+ integrations.

n8n.io

What is n8n?

n8n is a powerful, extendable workflow automation tool that allows users to create complex integrations between different applications without being constrained by proprietary platforms. It offers a visual interface where you can design workflows by connecting nodes representing various actions or triggers. Its open-source nature means you have full control over your data and can self-host your solution, making it ideal for businesses with specific security or compliance requirements.

Why Choose n8n?

  • Flexibility and Customization

Open Source:

With n8n, you get complete access to the source code, allowing you to customize workflows and integrate any service, regardless of whether it’s officially supported.

Self-Hosting:

Running n8n on your own infrastructure ensures that you control your data and comply with internal security policies.

Extensibility:

n8n’s modular architecture means you can easily extend its functionality by adding custom nodes or integrating new APIs.


  • Cost Efficiency

Free and Community-Driven:

n8n is free to use, and its active community continuously contributes plugins, integrations, and improvements.

No Vendor Lock-In:

Unlike many cloud-based solutions, n8n allows you to avoid being tied to a single vendor, giving you the freedom to scale and modify your workflows as needed.


  • Ease of Use

Visual Workflow Designer:

Its intuitive drag-and-drop interface simplifies the process of designing and managing automation flows.

Rich Ecosystem:

n8n supports a wide range of integrations, from popular cloud services to niche applications, reducing the need for custom API work.


Prerequisites for Launching n8n

Before you dive into the setup, ensure you have the following:

A Server or Local Environment: n8n can run on your local machine for testing or on a production server for live workflows. Docker (Recommended): For a streamlined and reproducible setup, using Docker is highly recommended. Node.js and npm: If you prefer a manual installation, ensure that you have Node.js (version 14 or higher) and npm installed. Basic Command Line Knowledge: Familiarity with terminal commands will help you navigate the installation and configuration process. SSL Certificate (for Production): If you plan to expose n8n to the internet, using an SSL certificate is crucial for securing communications.


Quick Start

Try n8n instantly with npx (requires Node.js):

npx n8n

Or deploy with Docker:

docker volume create n8n_data
docker run -it --rm --name n8n -p 5678:5678 -v n8n_data:/home/node/.n8n docker.n8n.io/n8nio/n8n

Resources

📚 Documentation

🔧 400+ Integrations

💡 Example Workflows

🤖 AI & LangChain Guide

👥 Community Forum

📖 Community Tutorials

Managing GitHub Actions Artifacts , A Simple Cleanup Guide

· 4 min read
Pourya Bagheri
Quantum Computing | Blockchain Soloution | MERN

When working with GitHub Actions, it’s common to generate a multitude of artifacts during builds, tests, and deployments. Over time, these artifacts can accumulate, taking up valuable space and making repository management more challenging. In many cases, you might find yourself needing to clean up these artifacts—whether to free up storage or simply to keep your project tidy.

In this article, we’ll discuss the problem of excess artifacts and provide a simple code example that can help you clean them up from outside GitHub.

The Problem: Too Many Artifacts

GitHub Actions provides a convenient way to build, test, and deploy your projects. However, every time an action runs, it can produce artifacts—files and reports that may be needed for debugging or archiving. While these artifacts can be invaluable for troubleshooting, they can also accumulate rapidly, especially in projects with frequent builds or extensive test suites.

Some common issues include:

- Storage Overhead:

Excess artifacts can occupy significant space, leading to potential storage limits or unnecessary clutter.

- Organization:

A large number of artifacts can make it hard to locate important information quickly.

- Performance:

Managing a cluttered repository might indirectly affect build performance or other maintenance tasks.

Why Clean Up Artifacts?

Cleaning up artifacts is not just about saving space; it also helps in maintaining a clean, organized repository. Regular cleanup routines can:

- Improve Readability:

Removing outdated or unnecessary files makes it easier for you and your team to navigate your repository.

- Ensure Compliance:

Some projects may have policies or storage limits, requiring periodic purging of unused artifacts.

- Enhance Performance:

A cleaner environment might lead to faster build times and fewer errors related to storage limits.

While GitHub itself offers some artifact retention policies, there are scenarios where you might need more granular control, especially when cleaning up from outside GitHub using scripts or external tools.

Cleaning Up Artifacts from Outside GitHub

Using GitHub’s REST API, you can programmatically list and delete artifacts. This method is particularly useful if you want to integrate cleanup into your CI/CD pipeline, schedule regular maintenance, or manage artifacts from an external system.

Below is a simple Python script that demonstrates how to list and delete artifacts from a GitHub repository. This code uses the requests library to interact with the GitHub API.

Sample Code: Python Script for Artifact Cleanup

import requests

# Replace with your GitHub personal access token
GITHUB_TOKEN = 'your_github_token'
# Replace with your repository details
OWNER = 'your_repo_owner'
REPO = 'your_repo_name'

# Set up the headers for authentication
headers = {
"Authorization": f"token {GITHUB_TOKEN}",
"Accept": "application/vnd.github.v3+json"
}

def list_artifacts():
"""List all artifacts in the repository."""
url = f"https://api.github.com/repos/{OWNER}/{REPO}/actions/artifacts"
response = requests.get(url, headers=headers)

if response.status_code != 200:
print(f"Failed to fetch artifacts: {response.status_code} - {response.text}")
return []

data = response.json()
return data.get('artifacts', [])

def delete_artifact(artifact_id, artifact_name):
"""Delete an artifact by its ID."""
delete_url = f"https://api.github.com/repos/{OWNER}/{REPO}/actions/artifacts/{artifact_id}"
response = requests.delete(delete_url, headers=headers)

if response.status_code == 204:
print(f"Deleted artifact '{artifact_name}' (ID: {artifact_id}) successfully.")
else:
print(f"Failed to delete artifact '{artifact_name}' (ID: {artifact_id}): {response.status_code} - {response.text}")

def cleanup_artifacts():
"""Fetch and delete all artifacts."""
artifacts = list_artifacts()

if not artifacts:
print("No artifacts found.")
return

print(f"Found {len(artifacts)} artifacts. Starting cleanup...")
for artifact in artifacts:
artifact_id = artifact['id']
artifact_name = artifact['name']
delete_artifact(artifact_id, artifact_name)

if __name__ == "__main__":
cleanup_artifacts()

How to Use the Script

  1. Install Dependencies: Ensure you have Python installed, and install the requests library if you haven’t already:
pip install requests
  1. Configure the Script: Replace the placeholders your_github_token, your_repo_owner, and your_repo_name with your actual GitHub personal access token and repository details.

  2. Run the Script: Execute the script from your command line:

python cleanup_artifacts.py

The script will list all artifacts and attempt to delete each one. You can modify the script to include filters (such as deleting only artifacts older than a certain date) based on your requirements.

Final Thoughts

Managing artifacts is a crucial aspect of maintaining a clean and efficient CI/CD workflow. While GitHub offers basic artifact management features, using external scripts like the one above provides you with greater control and flexibility. You can easily schedule this script using a cron job or integrate it into your own maintenance pipeline to ensure that your repository stays free of clutter.

Regular cleanup not only saves storage space but also helps in keeping your repository organized and performant. Feel free to customize the sample code to better fit your specific needs, such as filtering artifacts by creation date, size, or naming conventions.

Happy coding and maintain a tidy repository!

Setting Up Ollama and Running DeepSpeed on Linux

· 3 min read
Pourya Bagheri
Quantum Computing | Blockchain Soloution | MERN

Introduction

Ollama is a powerful tool for running large language models efficiently on local hardware. When combined with DeepSpeed, a deep learning optimization library, it enables even more efficient execution, particularly for fine-tuning and inference. In this guide, we will walk through the setup process for both Ollama and DeepSpeed on a Linux system.

Prerequisites

Before proceeding, ensure that your system meets the following requirements:

  • A Linux-based operating system (Ubuntu 20.04 or later recommended)

  • A modern NVIDIA GPU with CUDA support

  • Python 3.8 or later

  • Pip and Virtualenv installed

  • Sufficient storage and RAM for model execution

Step 1: Installing Ollama

Ollama provides an easy-to-use interface for managing large language models. To install it on Linux, follow these steps:

1. Open a terminal and update your system:

sudo apt update && sudo apt upgrade -y

2. Download and install Ollama:

curl -fsSL https://ollama.ai/install.sh | sh

3. Verify the installation:

ollama --version

alt text

If the installation was successful, you should see the version number displayed.

Step 2: Setting Up DeepSpeed

DeepSpeed optimizes deep learning models for better performance and scalability. To install and configure it:

1. Create and activate a Python virtual environment:

python3 -m venv deepspeed_env
source deepspeed_env/bin/activate

2. Install DeepSpeed and required dependencies:

pip install deepspeed torch transformers

3. Verify the installation:

deepspeed --version

Step 3: Running a Model with Ollama and DeepSpeed

Now that we have both tools installed, we can load a model and test it.

1. Pull a model with Ollama:

ollama pull mistral

This downloads the Mistral model, which we will use for testing.

2. Run inference with Ollama:

ollama run mistral "Hello, how are you?"

If successful, the model should generate a response.

3. Use DeepSpeed to optimize inference (example using a Hugging Face model):

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
import deepspeed

model_name = "meta-llama/Llama-2-7b"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name, torch_dtype=torch.float16)

ds_model = deepspeed.init_inference(model, dtype=torch.float16, replace_with_kernel_inject=True)

prompt = "What is DeepSpeed?"
inputs = tokenizer(prompt, return_tensors="pt").to("cuda")
outputs = ds_model.generate(**inputs)
print(tokenizer.decode(outputs[0]))

Example : Deepseek-r1 1.5b

alt text

Conclusion

By installing Ollama and DeepSpeed on Linux, you can efficiently run and optimize large language models. This setup enables users to leverage local hardware for AI model execution, reducing dependency on cloud services. If further fine-tuning or model adaptation is required, both tools provide advanced functionalities to enhance performance.

Setting Up Filecoin FVM Localnet for Smart Contract Development

· 3 min read
Pourya Bagheri
Quantum Computing | Blockchain Soloution | MERN

Filecoin FVM Localnet is a Docker-based solution that simplifies the process of deploying a local Filecoin network for smart contract development. This setup supports testing of Filecoin Virtual Machine (FVM) smart contracts and features such as replication between storage providers (SPs).

System Requirements

To run Filecoin FVM Localnet, you’ll need:

  • Processor Architecture: ARM64 (e.g., MacBook M1/M2) or AMD64 (e.g., x86 Linux, Windows, macOS).

  • Docker: Ensure Docker is installed on your system.


Installation

Step 1: Clone the Repository

Run the following command to clone the Filecoin FVM Localnet repository:

git clone https://github.com/filecoin-project/filecoin-fvm-localnet.git

Step 2: Navigate to the Repository

cd filecoin-fvm-localnet

Step 3: Configure the Environment

To use the default configuration with 2k sectors:

cp .env.example .env

To configure an 8MiB sector network, edit the .env file to enable the relevant settings.

Step 4: Start the Localnet

To run a single miner instance:

alt text

docker compose up

To run two miners with replication capabilities:

docker compose --profile replication up

Stop the network using Ctrl+C.

Step 5: Access the Boost UI

Once the localnet is running, you can access the Boost UI:


Setting Up Metamask

Configuring Metamask

  1. Open Metamask and click on the network dropdown at the top.

  2. Click Add a network manually and enter the following details:

Funding a Wallet

  1. Retrieve the t4 address for your wallet using the following command :
docker compose exec lotus lotus evm stat [wallet]
  1. Send test funds (tFIL) to your wallet using:
docker compose exec lotus lotus send <t4_address> 1000

Funds will appear in Metamask within approximately 45 seconds.


Usage Notes

Sector Sizes and Block Time

  • Default sector size: 2KiB (maximum storage deal size).

  • Optional: Configure for 8MiB sectors by editing .env and restarting the localnet.

  • Block time: 15 seconds (half the time of the Filecoin mainnet).

Resetting the Localnet

If the network takes a long time to sync, delete the data/ directory and restart the localnet to reset the state.


Common Commands for Filecoin FVM Localnet

Packing Files for Deals

  1. Pack files into CAR format:
ipfs-car pack [file] --output [filename].car
  1. Generate CommP for the packed CAR file:
boostx commp [file.car]

Creating a Storage Deal

boost deal --verified=false \
--provider=[minerId] \
--http-url=[file-address-on-server] \
--commp=<commp_value> \
--car-size=<car_file_size> \
--piece-size=<piece_size> \
--payload-cid=<payload_cid> \
--storage-price=[estimate-number] \
--duration=[time]

Checking Deal Status

Retrieve the status of a deal:

boost deal-status --provider=<provider_id> --deal-uuid=<deal_uuid>

Retrieving Stored Data

To retrieve stored data:

boost retrieve --provider=<provider_id> --output=/path/to/output/file.car <payload_cid>

NIST-FIPS-203 | Module-Lattice-Based Key-Encapsulation Mechanism Standard (ML-KEM)

· 13 min read
Pourya Bagheri
Quantum Computing | Blockchain Soloution | MERN

Module Lattice Based Key Encapsulation Mechanism Standard

An In-Depth Exploration of the ML-KEM Standard

The source provided is the official FIPS 203 document specifying the Module-Lattice-Based Key-Encapsulation Mechanism (ML-KEM) standard. It aims to provide a complete guide for implementing ML-KEM, a cryptographic algorithm designed to resist attacks from quantum computers. This response will explore the key concepts of the ML-KEM standard, the rationale behind its design, and important implementation considerations.

The Quantum Threat and the Rise of Post-Quantum Cryptography

Before examining ML-KEM itself, it is crucial to understand the context that led to its creation. Modern cryptography relies heavily on public-key cryptosystems, which are essential for tasks like secure key exchange and digital signatures. These cryptosystems are built upon mathematical problems that are computationally hard for classical computers to solve.

However, the advent of quantum computing presents a significant threat to these systems. Quantum computers leverage the principles of quantum mechanics to perform computations in a fundamentally different way than classical computers. This allows them to efficiently solve certain problems that are intractable for classical computers, including the factoring of large numbers and the discrete logarithm problem. These problems form the foundation of many widely used public-key cryptosystems, such as RSA and elliptic curve cryptography.

If large-scale, fault-tolerant quantum computers become a reality, they could break the security of these cryptosystems, rendering sensitive data vulnerable to attacks. To address this emerging threat, the field of post-quantum cryptography (PQC) has emerged. The goal of PQC is to develop cryptographic algorithms that are resistant to attacks from both classical and quantum computers.

Recognizing the urgency of this issue, NIST initiated the PQC Standardization process to evaluate and standardize new quantum-resistant public-key cryptographic algorithms. This process involved multiple rounds of public scrutiny, analysis, and evaluation of submitted candidate algorithms. ML-KEM emerged as one of the algorithms selected for standardization.

Key-Encapsulation Mechanisms: The Heart of Secure Key Exchange

ML-KEM is a specific type of cryptographic algorithm known as a key-encapsulation mechanism (KEM). KEMs are designed for the secure exchange of cryptographic keys between two parties over a public channel.

Understanding the Role of KEMs

In a typical key exchange scenario, two parties, often referred to as Alice and Bob, want to communicate securely. To do so, they need to establish a shared secret key. A KEM enables them to achieve this goal even if their communication channel is insecure and potentially eavesdropped upon. Here's a simplified overview of how a KEM works:

  • Key Generation: Alice uses a KEM's key generation algorithm to generate two keys: a public encapsulation key (analogous to a public key) and a private decapsulation key (analogous to a private key).
  • Encapsulation: Bob, upon receiving Alice's encapsulation key, uses the KEM's encapsulation algorithm to generate a shared secret key and an associated ciphertext.
  • Transmission: Bob sends the ciphertext to Alice.
  • Decapsulation: Alice, using her decapsulation key and the received ciphertext, runs the KEM's decapsulation algorithm to recover the shared secret key.

Key Properties of a Secure KEM:

  • Correctness: A KEM should ensure that if both parties follow the protocol correctly, they will derive the same shared secret key.
  • Security: A secure KEM must prevent an adversary from learning anything about the shared secret key even if they intercept the ciphertext and have access to -the encapsulation key.

ML-KEM: A Module-Lattice-Based Approach to Security

ML-KEM is based on a mathematical problem called the Module Learning With Errors (MLWE) problem. This problem is believed to be computationally hard, even for quantum computers. It leverages the structure of mathematical objects called modules, which are essentially generalizations of vector spaces. The MLWE problem involves finding a specific solution within a module, given a set of noisy linear equations. Let's break down the core concepts involved in the MLWE problem:

  • Modules: A module is an algebraic structure that consists of:

    • A set of elements.
    • An operation for adding elements (similar to vector addition).
    • An operation for multiplying elements by scalars (similar to scalar multiplication in vector spaces).
  • Lattices: Lattices are a specific type of module where the elements are represented by points in a grid-like structure. They play a crucial role in post-quantum cryptography due to their inherent geometric properties and the difficulty of certain computational problems related to them.

  • Learning With Errors (LWE) Problem: The LWE problem involves finding a secret vector given a set of noisy linear equations. The noise is intentionally added to make the problem difficult to solve.

  • Module Learning With Errors (MLWE) Problem: The MLWE problem extends the LWE problem to work with modules instead of vectors. This adds another layer of complexity to the problem, making it even more challenging for attackers to solve.

  • The security of ML-KEM is rooted in the assumption that solving the MLWE problem is computationally hard for both classical and quantum computers.

Building ML-KEM from K-PKE: A Two-Step Construction

The construction of ML-KEM proceeds in two steps:

  • Creating a Public-Key Encryption Scheme: First, the principles of the MLWE problem are used to construct a public-key encryption (PKE) scheme called K-PKE. This scheme allows for encryption and decryption of messages using a public and private key pair. However, K-PKE alone does not provide the desired level of security for key exchange.

  • Applying the Fujisaki-Okamoto (FO) Transform: To enhance the security of K-PKE and transform it into a robust KEM, the Fujisaki-Okamoto (FO) transform is applied. This transform is a well-established technique in cryptography that strengthens the security of a PKE scheme. It achieves this by:

  • Derandomizing the encryption process: This removes potential vulnerabilities arising from the use of predictable or weak randomness.

  • Adding checks and safeguards: The FO transform incorporates checks to ensure that the ciphertext is well-formed and has not been tampered with.

The resulting KEM, ML-KEM, is believed to satisfy a strong security notion called IND-CCA2 security. This security level ensures that the KEM remains secure even against sophisticated attacks, such as chosen-ciphertext attacks.

Enhancing Efficiency with the Number-Theoretic Transform

ML-KEM employs the number-theoretic transform (NTT) to optimize the performance of its operations. The NTT is a mathematical tool that enables efficient multiplication of polynomials. Polynomials play a key role in ML-KEM's calculations, and the NTT significantly speeds up these calculations. Understanding the NTT's Role:

  • Fast Polynomial Multiplication: Polynomial multiplication can be a computationally expensive operation. The NTT allows for faster multiplication by transforming polynomials into a different representation where multiplication is more efficient.

  • Transforming Between Representations: The NTT and its inverse transform can be used to convert between the standard representation of a polynomial and its NTT representation.

Illustrative Example:

Consider two polynomials, f(x) and g(x), that need to be multiplied.

  • Forward NTT: The NTT is applied to f(x) and g(x), resulting in their NTT representations, F and G.

  • Efficient Multiplication: F and G are multiplied in the NTT domain. This multiplication is faster in the NTT domain than in the standard polynomial representation.

  • Inverse NTT: The inverse NTT is applied to the product of F and G to obtain the product of f(x) and g(x) in the standard polynomial representation. This process of using the NTT for polynomial multiplication is considerably more efficient than directly multiplying f(x) and g(x). This efficiency gain is crucial for the performance of ML-KEM.

Parameter Sets: Balancing Security and Performance

ML-KEM offers three different parameter sets, each providing a different trade-off between security strength and performance:

  • ML-KEM-512 (Security Category 1): This parameter set offers a base level of security and the fastest performance. It is suitable for applications where performance is paramount and a moderate level of security is sufficient.

  • ML-KEM-768 (Security Category 3): This set provides enhanced security compared to ML-KEM-512, but it comes at the cost of slightly slower performance. It strikes a balance between security and performance and is suitable for a wide range of applications.

  • ML-KEM-1024 (Security Category 5): This parameter set provides the highest level of security but has the slowest performance among the three options. It is ideal for situations where maximum security is a top priority, even at the expense of some performance overhead.

The selection of the appropriate parameter set depends on the specific security requirements of the application and the available computational resources. Algorithms of ML-KEM: A Detailed Look

ML-KEM's functionality is implemented through three main algorithms:

  • ML-KEM.KeyGen (Algorithm 19 in the Sources):

  • This algorithm generates an encapsulation key and a corresponding decapsulation key.

  • The encapsulation key is made public, while the decapsulation key must be kept secret.

  • The generation process involves using a random bit generator (RBG) to create random seeds. These seeds are then used to generate the keys using various mathematical operations, including the NTT.

  • The sources recommend storing the seed generated during this process, as it can be used to regenerate the keys later, providing assurance of private key possession.

  • ML-KEM.Encaps (Algorithm 20 in the Sources):

  • This algorithm uses the encapsulation key (received from the other party) to create a shared secret key and a ciphertext.

  • The process begins with generating a random value, m.

  • The shared secret key, K, and a random value, r (used for encryption), are derived from m and the encapsulation key using hash functions.

  • The K-PKE encryption scheme is used to encrypt m using the encapsulation key and the randomness r, resulting in the ciphertext c.

  • The algorithm outputs the shared secret key K and the ciphertext c.

  • ML-KEM.Decaps (Algorithm 21 in the Sources):

  • This algorithm utilizes the decapsulation key (the party's own private key) and a received ciphertext to derive the shared secret key.

  • The decapsulation key contains several components: the decryption key of the K-PKE scheme, a hash value of the encapsulation key, and a random value z (used for implicit rejection in case of errors).

  • The K-PKE decryption algorithm is used to decrypt the ciphertext c and obtain a plaintext value m'.

  • To ensure correctness and prevent certain types of attacks, the algorithm re-encrypts m' using the derived randomness and compares the resulting ciphertext with the received ciphertext c.

  • If the ciphertexts match: The algorithm outputs the derived shared secret key, K'.

  • If the ciphertexts do not match: This indicates a potential error or attack. In this case, the algorithm performs an "implicit rejection" by deriving a different shared secret key based on the random value z and the ciphertext. This prevents the attacker from learning anything about the actual shared secret key.

Crucial Implementation Considerations

The sources emphasize the importance of adhering to specific implementation details to ensure the security and correctness of ML-KEM. Key considerations include:

  • Randomness Generation: The algorithms of ML-KEM heavily depend on randomness for generating keys, encryption randomness, and other operations. This randomness must be generated using an approved random bit generator (RBG) that meets specific security strength requirements. Using a weak or predictable RBG would compromise the security of the entire scheme.

  • Input Checking: Input checking is critical to prevent potential vulnerabilities that can arise from processing malformed or invalid inputs. ML-KEM mandates specific input checks for both encapsulation and decapsulation. These checks ensure that:

  • Encapsulation Key Check: The encapsulation key is a valid byte array with the correct length and encodes valid integers within the expected range.

  • Decapsulation Key Check: The decapsulation key has the correct length and contains internally consistent data.

  • Ciphertext Check: The ciphertext has the correct length for the chosen parameter set.

  • Prohibition of K-PKE as a Standalone Scheme: K-PKE, the public-key encryption scheme used as a building block for ML-KEM, is not sufficiently secure to be used as a standalone cryptographic scheme. It should only be employed within the context of the ML-KEM construction, where the FO transform and other security measures provide the necessary level of protection.

  • Controlled Access to Internal Functions: The ML-KEM scheme makes use of several internal functions, such as ML-KEM.KeyGen_internal, ML-KEM.Encaps_internal, and ML-KEM.Decaps_internal. These functions are designed for specific internal operations and should not be exposed directly to applications, except for testing purposes. The cryptographic module should handle the generation of random values and manage access to these internal functions to prevent potential misuse.

  • Proper Handling of Decapsulation Failures: While ML-KEM is designed to minimize decapsulation failures (cases where the decapsulated key does not match the encapsulated key), they can occur due to various factors, including transmission errors or intentional modifications of the ciphertext. The "implicit rejection" mechanism in ML-KEM.Decaps is essential for handling such failures securely. It ensures that even if an attacker intentionally causes a decapsulation failure, they cannot gain any information about the legitimate shared secret key.

  • Approved Usage of the Shared Secret Key: The shared secret key produced by ML-KEM should be used in accordance with established cryptographic guidelines. It can be directly used as a symmetric key or, if needed, further processed using an approved key derivation function (KDF) to create additional keys.

Differences from CRYSTALS-KYBER

While ML-KEM is based on the CRYSTALS-KYBER algorithm, there are some key differences that impact the input-output behavior of the algorithms:

Removal of Pre-Hashing in Encapsulation: In the third-round specification of CRYSTALS-KYBER, the initial randomness used in the ML-KEM.Encaps algorithm was hashed before use. This was intended as a safeguard against the potential use of flawed randomness. However, as ML-KEM mandates the use of approved RBGs, this pre-hashing step is deemed unnecessary and has been removed in the ML-KEM standard.

Inclusion of Explicit Input Checks: ML-KEM explicitly incorporates input checking steps in its algorithms to ensure the validity of the input data. These checks are designed to detect and prevent issues arising from malformed or invalid inputs. This is a security enhancement that was not explicitly included in the original CRYSTALS-KYBER specification.

Domain Separation in K-PKE.KeyGen: Based on comments received during the public draft phase of FIPS 203, domain separation was added to the K-PKE.KeyGen algorithm to prevent the misuse of keys generated for one security level at a different security level. This ensures that keys are used consistently with their intended security level.

Index Correction in Matrix A: During the initial public draft phase, the indices of the matrix A in K-PKE.KeyGen and K-PKE.Encrypt were inadvertently swapped. This has been corrected in the final version of ML-KEM to align with the CRYSTALS-KYBER specification, ensuring consistency and proper functionality.

Concluding Remarks

The ML-KEM standard marks a significant step towards securing digital communications in the age of quantum computing. It leverages the strength of lattice-based problems, believed to be resistant to quantum attacks, to provide a robust mechanism for secure key exchange.

The sources provide a comprehensive and detailed technical specification of ML-KEM, highlighting its algorithms, parameter sets, and critical implementation considerations. The differences between ML-KEM and its predecessor, CRYSTALS-KYBER, are outlined to facilitate a smooth transition for implementers.

The standard is primarily targeted towards technical audiences involved in implementing and deploying cryptographic systems. While it offers insights into the rationale and security considerations behind design choices, it assumes a good understanding of cryptographic concepts and mathematical principles.

Reference : https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.ipd.pdf

Trusted Execution Environment (TEE) with Rust and AWS

· 5 min read
Pourya Bagheri
Quantum Computing | Blockchain Soloution | MERN

Trusted Execution Environment (TEE) with Rust and AWS

Trusted Execution Environments (TEEs) are critical for modern applications where sensitive data needs to be processed securely. By isolating code execution from the rest of the system, TEEs provide a secure enclave where data and computations are shielded from unauthorized access, even in cases where the operating system is compromised. In this article, we will explore how to leverage TEEs using Rust—a system programming language known for its safety and performance—along with AWS services to build secure and efficient applications.


Overview of TEE

Key Features of TEE

  • Isolation: Secure enclave segregates sensitive code and data from the rest of the system.

  • Attestation: Remote parties can verify the integrity of the TEE before trusting it with sensitive data.

  • Encryption: Data within the TEE is encrypted and inaccessible from outside.

Use Cases of TEE

  • Secure key management

  • Processing confidential data, such as financial transactions

  • Privacy-preserving machine learning


Why Use Rust for TEE?

Rust is an excellent choice for working with TEEs due to its:

  • Memory Safety: Rust prevents common vulnerabilities like buffer overflows.

  • Concurrency Without Data Races: Rust’s ownership model ensures safe multithreading.

  • Performance: Rust’s zero-cost abstractions deliver C-like performance.

Additionally, Rust has libraries and tools to interact with TEEs, such as Intel SGX SDKs and AMD SEV frameworks.


TEE on AWS

AWS provides various services to integrate TEEs into your applications:

  • AWS Nitro Enclaves: Isolate sensitive computations in secure enclaves on AWS EC2 instances.

  • AWS Key Management Service (KMS): Manage encryption keys securely.

  • AWS Lambda with AWS Enclaves: Enable serverless applications to process sensitive data securely.


Implementing a Secure TEE Application with Rust and AWS

In this section, we will create a secure application using AWS Nitro Enclaves and Rust. Our application will:

  1. Receive sensitive data.

  2. Process the data securely in a Nitro Enclave.

  3. Return the result to the client.

Prerequisites

  1. Rust Development Environment: Install Rust and set up your development environment using rustup.

  2. AWS CLI and Nitro CLI: Install and configure these tools on your EC2 instance.

  3. Nitro Enclaves-enabled EC2 Instance: Launch an EC2 instance with support for Nitro Enclaves.


Step 1: Setting Up the Nitro Enclave

Configure Your EC2 Instance

Ensure your EC2 instance is Nitro Enclaves-compatible and has enclave support enabled:

sudo nitro-cli-config -i sudo nitro-cli-config -m auto

Build the Enclave Image

Create an enclave image file (eif) containing the application binary:

docker build -t enclave-app .
nitro-cli build-enclave --docker-uri enclave-app --output-file enclave.eif

Run the Enclave

Launch the enclave using Nitro CLI:

nitro-cli run-enclave --eif-path enclave.eif --memory 2048 --cpu-count 2

Step 2: Developing the Rust Application

Application Requirements

The Rust application will:

  • Listen for client requests.

  • Process sensitive data securely within the enclave.

  • Return encrypted responses.

Application Code

Here’s the Rust code for the application:

main.rs:

use std::io::{Read, Write};
use std::net::{TcpListener, TcpStream};
use serde::{Deserialize, Serialize};
use aes_gcm::{Aes256Gcm, Key, Nonce}; // Encryption library
use aes_gcm::aead::{Aead, NewAead};

#[derive(Serialize, Deserialize)]
struct Request {
message: String,
}

#[derive(Serialize, Deserialize)]
struct Response {
encrypted_message: Vec<u8>,
}

fn handle_client(mut stream: TcpStream, key: &Key) {
let mut buffer = [0; 1024];
stream.read(&mut buffer).unwrap();

let request: Request = serde_json::from_slice(&buffer).unwrap();
println!("Received: {}", request.message);

// Encrypt the message
let cipher = Aes256Gcm::new(key);
let nonce = Nonce::from_slice(b"unique nonce");
let ciphertext = cipher.encrypt(nonce, request.message.as_bytes()).unwrap();

let response = Response {
encrypted_message: ciphertext,
};

let response_json = serde_json::to_vec(&response).unwrap();
stream.write_all(&response_json).unwrap();

}

fn main() {
let listener = TcpListener::bind("0.0.0.0:8080").unwrap();
println!("Server listening on port 8080");

// Generate a secure key for encryption
let key = Key::from_slice(b"an example very very secret key.");

for stream in listener.incoming() {
match stream {
Ok(stream) => {
handle_client(stream, key);
}
Err(e) => {
eprintln!("Error: {}", e);
}
}
}

}

Key Points

  • Encryption: The application uses AES-256-GCM to encrypt data securely.

  • Serialization: Rust’s serde library handles JSON serialization/deserialization.


Step 3: Integrating with AWS KMS

Use AWS KMS to manage and provision encryption keys:

Example: Encrypting Data with KMS

aws kms encrypt \
--key-id alias/YourKMSKeyAlias \
--plaintext fileb://plaintext-file \
--output text \
--query CiphertextBlob > encrypted-file

Decrypt the data inside the enclave using the AWS KMS API.


Step 4: Secure Communication

Secure communication between the client and the enclave using TLS. You can use libraries like rustls or tokio for TLS support.

Example: Adding TLS to the Server

use tokio_rustls::TlsAcceptor;
use tokio::net::TcpListener;

// Implement TLS listener with certificate and private key.

Testing the TEE Application

  • Unit Testing: Test individual Rust functions, especially encryption and decryption.

  • Integration Testing: Verify communication between the client and the enclave.

  • End-to-End Testing: Simulate real-world scenarios to ensure data is processed securely.


Conclusion

Combining Rust’s safety features with AWS Nitro Enclaves allows developers to build highly secure applications that process sensitive data. By leveraging TEEs, you can achieve data isolation, integrity, and confidentiality even in hostile environments. With the provided example, you now have a foundation to build your own TEE-powered applications using Rust and AWS.

The Best Decentralized Storage Solutions in the Market

· 6 min read
Pourya Bagheri
Quantum Computing | Blockchain Soloution | MERN

The Best Decentralized Storage Solutions in the Market

Introduction to Decentralized Storage Services

With the increasing demand for more secure, private, and efficient methods of storing data, decentralized storage solutions have emerged as an alternative to traditional centralized cloud storage services. These services leverage blockchain technology and distributed networks to store data across multiple nodes, offering users enhanced security, privacy, and fault tolerance. In this article, we will explore several popular decentralized storage solutions: Filebase, Storj, Filecoin, Web3.Storage, IPFS, Infura, and Moralis. We will examine their features, benefits, and drawbacks.

1. Filebase

Filebase provides an easy-to-use platform for decentralized storage by offering users an interface to store and manage data on top of decentralized networks like Sia and Storj. It acts as a gateway for decentralized storage networks, simplifying the process of interacting with them.

Advantages:

  • Easy to integrate with existing applications through S3-compatible APIs.
  • Reliable and redundant data storage with geographic distribution.
  • Data is encrypted by default, offering additional security.

Disadvantages:

  • The pricing structure may be complex for some users.
  • Limited scalability compared to other systems like Filecoin.

2. Storj

  • Storj is a decentralized cloud storage platform built on blockchain technology. It encrypts data and splits it into fragments that are distributed across a network of nodes. Storj ensures privacy and security by utilizing end-to-end encryption.

Advantages:

  • High security and encryption of data.
  • Redundant storage with a global network of nodes.
  • Decentralized, meaning no single point of failure.
  • Cost-effective for users compared to traditional cloud storage.

Disadvantages:

  • Network performance can fluctuate based on node availability.
  • Still in development with evolving features and protocols.

3. Filecoin

Filecoin is a decentralized storage network and cryptocurrency designed to enable users to rent out spare storage space while also allowing users to store their data on a distributed network. It operates using a native cryptocurrency to incentivize storage providers.

Advantages:

  • Scalable and designed for long-term data storage.
  • Strong ecosystem and support from the blockchain community.
  • Offers high flexibility in terms of storage contracts and options.

Disadvantages:

  • High storage cost compared to other decentralized storage options.
  • Complexity of integrating with the Filecoin network.
  • Reliant on the Filecoin blockchain, meaning fluctuations in the cryptocurrency's price could affect costs.

4. Web3.storage

Web3.Storage is a decentralized storage service focused on storing data for Web3 applications. It uses the InterPlanetary File System (IPFS) and Filecoin to provide scalable, distributed storage for developers.

Advantages:

  • Easy to use, with straightforward APIs.
  • Integrated with Filecoin, making it scalable and reliable.
  • Ideal for Web3 projects, providing a seamless connection with other decentralized applications.

Disadvantages:

  • Mainly targeted toward Web3 developers, limiting its broader appeal.
  • Reliant on both IPFS and Filecoin, which may introduce complexity in some use cases.

5. IPFS (InterPlanetary File System)

IPFS is a peer-to-peer file sharing system that stores files in a decentralized manner. Rather than relying on a central server, IPFS allows users to store and retrieve files from a distributed network.

Advantages:

  • Content addressing makes files immutable and verifiable.
  • Highly efficient data retrieval and distribution.
  • Ideal for decentralized applications and reducing reliance on centralized servers.

Disadvantages:

  • Data permanence is not guaranteed unless paired with storage solutions like Filecoin.
  • Nodes must be consistently online to ensure availability.
  • Performance issues with large files or high demand on the network.

6. Infura

Infura is a development platform that provides infrastructure for building decentralized applications (dApps) without needing to run your own Ethereum or IPFS node. It acts as a bridge to decentralized storage solutions like IPFS.

Advantages:

  • No need to run your own node, simplifying development.
  • Reliable and highly available service with robust infrastructure.
  • Used widely within the Ethereum ecosystem.

Disadvantages:

  • Not a purely decentralized service since Infura is a centralized platform.
  • Users must trust Infura to access and store data reliably.

7. Moralis

Moralis provides a powerful backend infrastructure for building decentralized applications, including file storage solutions that integrate with IPFS and other decentralized networks. It aims to simplify the development of Web3 applications.

Advantages:

  • Easy integration with Web3 projects.
  • Includes features such as decentralized authentication, data storage, and real-time notifications.
  • Supports multiple blockchain networks.

Disadvantages:

  • Relies on centralized services, which can limit the "decentralization" aspect for some use cases.
  • The platform is in active development and may have evolving features.

8. Arweave

Arweave is a decentralized storage platform that focuses on permanent data storage. Unlike other decentralized storage services that rely on rented storage space, Arweave uses a blockchain-based "permaweb" to store data permanently. Arweave's model encourages long-term storage by having users pay a one-time fee for permanent access to the stored data.

Advantages:

  • Data permanence is guaranteed by the blockchain, ensuring that once data is uploaded, it remains accessible forever.
  • Built-in incentives for storing data permanently.
  • Cost-effective in the long run due to the one-time payment model.

Disadvantages:

  • The cost may be higher for large-scale storage compared to some other services.
  • Not suitable for all types of data, especially for those requiring frequent updates or temporary storage.

9. Pinata

Pinata is a cloud-based IPFS pinning service that provides a way for developers to store and manage files on the IPFS network. By offering reliable and efficient pinning, Pinata ensures that files remain accessible across the distributed network.

Advantages:

  • Easy-to-use platform with an intuitive API.
  • Provides reliable pinning services for IPFS, ensuring data availability.
  • Allows developers to interact with the IPFS network without maintaining their own infrastructure.
  • Supports a variety of file types and use cases.

Disadvantages:

  • Relies on a centralized service for pinning, which may contradict the fully decentralized ethos of IPFS.
  • Costs may accumulate with heavy usage, especially for high-volume projects.
  • Requires trust in Pinata for consistent data availability.

Conclusion

Decentralized storage solutions are rapidly evolving, and each service has its own set of strengths and weaknesses. Services like Filebase and Web3.Storage aim to simplify decentralized storage for developers, while platforms like Storj and Filecoin offer scalable solutions with a focus on privacy and security. However, some services still face challenges regarding scalability, performance, and the balance between decentralization and centralization. As the Web3 ecosystem continues to grow, decentralized storage solutions are likely to play a crucial role in shaping the future of data storage and management.

Docker cli cheat sheet

· 3 min read
Pourya Bagheri
Quantum Computing | Blockchain Soloution | MERN

Docker cli cheat sheet

Displays the installed version of Docker.

docker --version

Shows system-wide information about Docker including the number of containers, images, and more.

docker info

Pulls a Docker image from Docker Hub or another registry.

docker pull <image_name>

Builds an image from a Dockerfile located in the specified directory.

docker build -t <tag_name> <path>

Lists all available Docker images on your local machine.

docker images

Lists all running containers.

docker ps

Lists all containers, including stopped ones.

docker ps -a

Runs a container from the specified image.

docker run <image_name>

Runs a container in detached mode.

docker run -d <image_name>

Maps a port on the host machine to a port in the container.

docker run -p <host_port>:<container_port> <image_name>

Executes a command inside a running container.

docker exec -it <container_id> <command>

Stops a running container.

docker stop <container_id>

Starts a stopped container.

docker start <container_id>

Restarts a running or stopped container.

docker restart <container_id>

Removes a stopped container.

docker rm <container_id>

Removes a Docker image.

docker rmi <image_id>

Fetches logs of a running or stopped container.

docker logs <container_id>

Lists all Docker networks.

docker network ls

Lists all Docker volumes.

docker volume ls

Starts up all containers defined in the docker-compose.yml file.

docker-compose up

Stops and removes all containers defined in the docker-compose.yml file.

docker-compose down

Builds images for the services defined in the docker-compose.yml file.

docker-compose build

Fetches logs for all containers defined in the docker-compose.yml file.

docker-compose logs

Lists files inside a running container.

docker exec <container_id> ls

Lists all Docker images, including intermediate layers.

docker images -a

Builds an image without using cache, ensuring all steps are re-executed.

docker build --no-cache -t <tag_name> .

Retrieves detailed information about a container or image.

docker inspect <container_id>

Opens an interactive bash shell inside a running container.

docker exec -it <container_id> bash

Customizes the output of the docker info command.

docker info --format '{{.Containers}}'

Attaches to a running container's standard input, output, and error streams.

docker attach <container_id>

Displays live statistics of running containers.

docker stats

Pulls all tags of a Docker image.

docker pull --all-tags <image_name>

Tags an image with a new name.

docker tag <image_id> <new_image_name>

Copies files or directories from a container to the host.

docker cp <container_id>:<container_path> <host_path>

Copies files or directories from the host to a container.

docker cp <host_path> <container_id>:<container_path>

Automatically removes the container when it stops.

docker run --rm <image_name>

Logs in to a Docker registry.

docker login <registry_url>

Logs out from a Docker registry.

docker logout

Removes unused Docker objects like containers, networks, and volumes.

docker prune

Retrieves detailed information about a Docker network.

docker network inspect <network_name>

Dynamic circuits enable circuit cutting for quantum supercomputing

· 2 min read
Pourya Bagheri
Quantum Computing | Blockchain Soloution | MERN

The research paper published in Nature discusses a significant step forward in quantum computing, specifically focusing on how two connected quantum processors can work together to execute a quantum circuit that is too large for either processor to handle on its own. This breakthrough is important because it marks the first demonstration of using multiple quantum processors in tandem, a concept that could help scale quantum computing for larger, more complex problems.

alt text Reference: Source of the image

Currently, most classical supercomputers are built by connecting many CPUs and GPUs together to solve big problems. The researchers suggest that quantum computers of the future will follow a similar approach, using multiple quantum processing units (QPUs) working together. This is part of a larger vision of Quantum-Centric Supercomputing (QCSC), where quantum processors and classical computers work side by side to tackle computational tasks.

alt text Reference: Source of the image

To enable this, the researchers used a technique called "circuit cutting," which allows a large quantum circuit to be divided into smaller pieces that can be handled by individual QPUs. They then used classical computers to combine the results of these sub-circuits. The main challenge here is performing two-qubit operations (which are fundamental to quantum computing) between qubits located on different processors. The team developed a method using "virtual gates" and a process called teleportation to simulate entanglement between qubits on separate processors, which made it possible to perform these operations across two QPUs.

The researchers also tackled the issue of errors that occur when quantum processors "idle" during the process. They created an innovative error mitigation strategy, improving the accuracy of the quantum calculations. This is crucial because even small errors can significantly impact the results of quantum computations.

alt text Reference: Source of the image

One of the main outcomes of this research is that it extends the capabilities of quantum hardware beyond the limitations of single processors. For example, the team was able to simulate a quantum state with 142 qubits using two 127-qubit processors. This is an important advancement for future quantum computing applications, such as simulating natural systems or improving quantum error correction techniques.

alt text Reference: Source of the image

Ultimately, this research shows that even with current quantum processors, it’s possible to explore larger, more complex problems, and it paves the way for future breakthroughs in quantum computing and supercomputing.