0.0.2 • Published 6 months ago

soda-sdk v0.0.2

Weekly downloads
-
License
MIT
Repository
github
Last release
6 months ago

Soda-sdk

This SDK provides functionalities for AES and RSA encryption schemes, ECDSA signature scheme and some functionalties used for working with sodalabs interface. The SDK provide the all functionalities in three common widely used languages - Golang, Python and JavaScript.

The SDK also provides a CLI in Golang that provides functionalities for AES encryption scheme.

Table of Contents

Available functionalities

The SDK support provide the following functionalities:

  • AES encryption scheme:

    • Generate AES key
    • Encrypt
    • Decrypt
  • RSA encryption scheme:

    • Generate RSA key pair
    • Encrypt
    • Decrypt
  • ECDSA signature scheme:

    • Generate ECDSA private key
    • Sign
  • Hash:

    • Keccak 256
  • Functionalities related to sodalabs InputText:

    • Sign InputText function

      This function gets:

      • sender address bytes
      • contract address bytes
      • hashed function signature bytes
      • ciphertext bytes
      • ECDSA private key bytes.

        It appends the addresses, signature and ciphertext and signs the appended string using the private key.

    • Verify IT (Available only in Golang) This function gets:

      • sender address bytes
      • contract address bytes
      • hashed function signature bytes
      • ciphertext bytes
      • signature

        It verify the signature against the received data

    • Prepare InputText function

      This function gets:

      • plaintext
      • AES key
      • sender address
      • contract address
      • function signature (as string in go and python case, or hashed in js case)
      • ECDSA private key.

        It encrypt the plaintext using the AES key to get the ciphertext, then sign the concatination of the addresses, hashed function signature and ciphertext using the ECDSA private key.

    • Get function signature

      This function get the function signature as a string and returned the keccak-256 value on the signature

Installation

Clone the repository:

git clone https://github.com/soda-mpc/soda-sdk.git

Golang

Prerequisites

Go (Golang) installed on your system.

Compilation

Navigate to the project directory:

cd soda-sdk/golang_cli

Build the project:

go build

Usage

Below is an example function from the Golang test file that demonstrate the signature functionality. Lets break it down:

func TestSignature(t *testing.T) {
    # Create random values for the sender and contract addresses and function signature
	sender := make([]byte, AddressSize)
	_, err := rand.Read(sender)
	addr := make([]byte, AddressSize)
	_, err = rand.Read(addr)
	funcSig := make([]byte, FuncSigSize)
	_, err = rand.Read(funcSig)

    # Generate ECDSA private key
	key := GenerateECDSAPrivateKey()
	require.NoError(t, err, "Failed to generate random key")

	# Create plaintext with the value 100 
	plaintextValue := big.NewInt(100)
	plaintextBytes := plaintextValue.Bytes()
    # Encrypt the plaintext 
	ciphertext, r, err := Encrypt(key, plaintextBytes)
	require.NoError(t, err, "Encrypt should not return an error")

	ct := append(ciphertext, r...)

	# Sign the sender, contract, function signature and ct using the generated ECDSA private key
	signature, err := SignIT(sender, addr, funcSig, ct, key)
	require.NoError(t, err, "Sign should not return an error")

	# Verify the signature
	verified := VerifyIT(sender, addr, funcSig, ct, signature)
	assert.Equal(t, verified, true, "Verify signature should return true")
}

Python

Prerequisites

Python should be installed on your system.

Additionally, install the required libraries using the following commands:

pip install pycryptodome
pip install eth-keys
pip install cryptography
pip install web3

Usage

In order to use the functionalities of python SDK, first import the modules from 'crypto' file. for example:

from crypto import prepare_IT, decrypt

Below is an example function from the python test file that demonstrate using some of the SDK functionality. Lets break it down:

def test_prepareIT(self):
    # Create inputs for prepare_IT function
    plaintext = 100                                                     # plaintext 
    userKey = bytes.fromhex("b3c3fe73c1bb91862b166a29fe1d63e9")         # AES key
    sender = Account()                                                  # Sender account
    sender.address = "0xd67fe7792f18fbd663e29818334a050240887c28"
    contract = Account()                                                # Contract account
    contract.address = "0x69413851f025306dbe12c48ff2225016fc5bbe1b"
    func_sig = "test(bytes)"                                            # function signature as string
    signingKey = bytes.fromhex("3840f44be5805af188e9b42dda56eb99eefc88d7a6db751017ff16d0c5f8143e")  # ECDSA private key

    # Call prepare_IT function with the plaintext, AES key, sender and contract accounts, function signature and ECDSA private key
    ct, signature = prepare_IT(plaintext, userKey, sender, contract, func_sig, signingKey)
    # prepare_IT returns the ciphertext and the signature

    # Verify the signature
    sender_address_bytes = bytes.fromhex(sender.address[2:])     # Get the bytes of the accounts addresses
    contract_address_bytes = bytes.fromhex(contract.address[2:])
    func_hash = get_func_sig(func_sig)                           # Create the function signature
    # Create the signed message 
    message = sender_address_bytes + contract_address_bytes + func_hash + ctBytes
    pk = keys.PrivateKey(signingKey)
    signature = keys.Signature(signature)
    # Verify the signature against the message hash and the public key
    verified = signature.verify_msg(message, pk.public_key)
    self.assertEqual(verified, True)

    # Decrypt the ciphertext using the AES key and check the decrypted value agains the original plaintext
    ctBytes = ct.to_bytes((ct.bit_length() + 7) // 8, 'big')
    
    # ctBytes is divided into two components: random and encrypted data. The decrypt function processes each component separately. 
    decrypted = decrypt(userKey, ctBytes[block_size:], ctBytes[:block_size])
    decrypted_integer = int.from_bytes(decrypted, 'big')
    self.assertEqual(plaintext, decrypted_integer)

This example uses the prepare_IT and decrypt functionalities of the python SDK. More examples can be found in the test.py file.

JavaScript

Prerequisites

JavaScript should be installed on your system. Additionally, navigate to the js directory and install the necessary JavaScript libraries by:

npm install

Usage

In order to use the functionalities of JavaScript SDK, first import the modules from 'crypto' file. for example:

import { encrypt } from './crypto.mjs';

Below is an example of RSA encryption scheme. The code can be found in the test.mjs file, lets break it down:

const plaintext = Buffer.from('I love soda labs');
# Generate RSA key pair
const { publicKey, privateKey } = generateRSAKeyPair();

# Encrypt the plaintext using the public key
const ciphertext = encryptRSA(publicKey, plaintext);

# Decrypt the ciphertext
const decrypted = decryptRSA(privateKey, ciphertext);

# Check the decrypted value agains the original plaintext
assert.deepStrictEqual(plaintext, decrypted);

Running tests

We offer a test file for each supported language.

It's important to note that running tests from inner directories is not advisable. Some tests rely on the output of others, and the execution order is critical. Running tests out of order may lead to failures.

To run the tests correctly, use a bash file that executes the tests in the proper sequence. Navigate to the main directory and execute the following command:

./testAll.sh

After running the tests using the provided bash file, the outcomes of the tests will be shown in your terminal or command prompt window. This output typically includes information about which tests passed, failed, or encountered errors, along with any additional details or logs generated during the testing process. It's essential to review this output to ensure that all tests have executed as expected and to address any issues that may have arisen.

Golang CLI Tool for a random AES Encryption and Decryption

This command-line tool provides functionalities for encrypting and decrypting data using AES encryption. It also supports key generation and storage.

Usage

cli-tool [OPTIONS]

Options:

  • --help: Show help message

  • --encrypt: Encrypt data.Provide a filename and plaintext as an additional argument.

  • --decrypt: Decrypt data. Provide a filename and two encrypted hex strings as additional arguments.

  • --generate-key: Generate key and save to specified file. Provide a filename.

Examples:

Encryption:

cli-tool --encrypt keyfile.txt 1234567890123456

Decryption:

cli-tool --decrypt keyfile.txt <encrypted-hex-string> <random-hex-string>

Generate Key:

cli-tool --generate-key mykey.txt