luajitos

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

IMPORT_EXAMPLE.md (11689B)


      1 # Importing Crypto Library in Other Apps
      2 
      3 This document shows how to import and use the crypto library from other LuajitOS applications.
      4 
      5 ## Quick Start
      6 
      7 ### Step 1: Update Your Manifest
      8 
      9 Add `import` and `run` permissions to your app's `manifest.lua`:
     10 
     11 ```lua
     12 return {
     13     name = "myapp",
     14     developer = "mydev",
     15     version = "1.0.0",
     16     entry = "src/init.lua",
     17     mode = "cli",  -- or "gui"
     18     permissions = {
     19         "stdio",
     20         "import",  -- Required to import from other apps
     21         "run"      -- Required to run the crypto app
     22     }
     23 }
     24 ```
     25 
     26 ### Step 2: Import Crypto in Your Code
     27 
     28 In your `src/init.lua`:
     29 
     30 ```lua
     31 -- Run the crypto app to initialize exports
     32 run("crypto")
     33 
     34 -- Import the crypto library
     35 local cryptoApp = apps["com.luajitos.crypto"]
     36 if not cryptoApp then
     37     print("Error: crypto app not found")
     38     return
     39 end
     40 
     41 local crypto = cryptoApp:call("crypto")
     42 if not crypto then
     43     print("Error: failed to import crypto library")
     44     return
     45 end
     46 
     47 -- Now you can use all crypto functions!
     48 local hash = crypto.SHA256("Hello World")
     49 
     50 -- Convert binary hash to hex for display
     51 local function toHex(data)
     52     local hex = ""
     53     for i = 1, #data do
     54         hex = hex .. string.format("%02x", string.byte(data, i))
     55     end
     56     return hex
     57 end
     58 
     59 print("SHA256 hash: " .. toHex(hash))
     60 ```
     61 
     62 ## Complete Examples
     63 
     64 ### Example 1: Simple Hash Calculator
     65 
     66 ```lua
     67 -- com.mydev.hashcalc/manifest.lua
     68 return {
     69     name = "hashcalc",
     70     developer = "mydev",
     71     version = "1.0.0",
     72     entry = "src/init.lua",
     73     mode = "cli",
     74     permissions = {"stdio", "import", "run"}
     75 }
     76 
     77 -- com.mydev.hashcalc/src/init.lua
     78 run("crypto")
     79 local crypto = apps["com.luajitos.crypto"]:call("crypto")
     80 
     81 local function toHex(data)
     82     local hex = ""
     83     for i = 1, #data do
     84         hex = hex .. string.format("%02x", string.byte(data, i))
     85     end
     86     return hex
     87 end
     88 
     89 local data = args[1] or "test"
     90 
     91 print("Input: " .. data)
     92 print("MD5:      " .. toHex(crypto.MD5(data)))
     93 print("SHA1:     " .. toHex(crypto.SHA1(data)))
     94 print("SHA256:   " .. toHex(crypto.SHA256(data)))
     95 print("BLAKE2b:  " .. toHex(crypto["BLAKE2b-256"](data)))
     96 ```
     97 
     98 Usage: `hashcalc "hello world"`
     99 
    100 ### Example 2: Password Manager
    101 
    102 ```lua
    103 -- com.mydev.pwdmgr/manifest.lua
    104 return {
    105     name = "pwdmgr",
    106     developer = "mydev",
    107     version = "1.0.0",
    108     entry = "src/init.lua",
    109     mode = "cli",
    110     permissions = {"stdio", "import", "run", "filesystem"}
    111 }
    112 
    113 -- com.mydev.pwdmgr/src/init.lua
    114 run("crypto")
    115 local crypto = apps["com.luajitos.crypto"]:call("crypto")
    116 
    117 local function toHex(data)
    118     local hex = ""
    119     for i = 1, #data do
    120         hex = hex .. string.format("%02x", string.byte(data, i))
    121     end
    122     return hex
    123 end
    124 
    125 local function fromHex(hex)
    126     local binary = ""
    127     for i = 1, #hex, 2 do
    128         local byte = tonumber(hex:sub(i, i+1), 16)
    129         binary = binary .. string.char(byte)
    130     end
    131     return binary
    132 end
    133 
    134 -- Hash a password with a random salt
    135 local function hashPassword(password)
    136     local salt = crypto.generateSalt()
    137     local hash = crypto.PBKDF2(password, salt, 100000, 32)
    138 
    139     return {
    140         salt = toHex(salt),
    141         hash = toHex(hash)
    142     }
    143 end
    144 
    145 -- Verify a password against stored hash
    146 local function verifyPassword(password, salt_hex, hash_hex)
    147     local salt = fromHex(salt_hex)
    148     local stored_hash = fromHex(hash_hex)
    149     local computed_hash = crypto.PBKDF2(password, salt, 100000, 32)
    150 
    151     return computed_hash == stored_hash
    152 end
    153 
    154 -- Example usage
    155 print("Password Manager Example")
    156 print("")
    157 
    158 -- Hash a password
    159 local password = "MySecurePassword123"
    160 print("Hashing password: " .. password)
    161 local result = hashPassword(password)
    162 print("Salt: " .. result.salt)
    163 print("Hash: " .. result.hash)
    164 print("")
    165 
    166 -- Verify correct password
    167 print("Verifying correct password...")
    168 if verifyPassword(password, result.salt, result.hash) then
    169     print("✓ Password verified!")
    170 else
    171     print("✗ Password verification failed")
    172 end
    173 
    174 -- Verify wrong password
    175 print("")
    176 print("Verifying wrong password...")
    177 if verifyPassword("WrongPassword", result.salt, result.hash) then
    178     print("✓ Password verified!")
    179 else
    180     print("✗ Password verification failed (expected)")
    181 end
    182 ```
    183 
    184 Usage: `pwdmgr`
    185 
    186 ### Example 3: Digital Signature Tool
    187 
    188 ```lua
    189 -- com.mydev.signer/manifest.lua
    190 return {
    191     name = "signer",
    192     developer = "mydev",
    193     version = "1.0.0",
    194     entry = "src/init.lua",
    195     mode = "cli",
    196     permissions = {"stdio", "import", "run"}
    197 }
    198 
    199 -- com.mydev.signer/src/init.lua
    200 run("crypto")
    201 local crypto = apps["com.luajitos.crypto"]:call("crypto")
    202 
    203 local function toHex(data)
    204     local hex = ""
    205     for i = 1, #data do
    206         hex = hex .. string.format("%02x", string.byte(data, i))
    207     end
    208     return hex
    209 end
    210 
    211 print("Ed25519 Digital Signature Tool")
    212 print("")
    213 
    214 -- Generate keypair
    215 print("Generating Ed25519 keypair...")
    216 local pubkey, privkey = crypto.sign.Ed25519.keypair()
    217 print("Public Key:  " .. toHex(pubkey))
    218 print("Private Key: " .. toHex(privkey))
    219 print("")
    220 
    221 -- Sign a message
    222 local message = "This is a signed message"
    223 print("Signing message: " .. message)
    224 local signature = crypto.sign.Ed25519.sign(message, privkey)
    225 print("Signature: " .. toHex(signature))
    226 print("")
    227 
    228 -- Verify signature
    229 print("Verifying signature...")
    230 local valid = crypto.sign.Ed25519.verify(message, signature, pubkey)
    231 if valid then
    232     print("✓ Signature is VALID")
    233 else
    234     print("✗ Signature is INVALID")
    235 end
    236 print("")
    237 
    238 -- Try to verify tampered message
    239 local tampered = "This is a tampered message"
    240 print("Verifying tampered message: " .. tampered)
    241 local valid2 = crypto.sign.Ed25519.verify(tampered, signature, pubkey)
    242 if valid2 then
    243     print("✓ Signature is VALID")
    244 else
    245     print("✗ Signature is INVALID (expected)")
    246 end
    247 ```
    248 
    249 Usage: `signer`
    250 
    251 ### Example 4: Key Exchange Demo
    252 
    253 ```lua
    254 -- com.mydev.keyexchange/manifest.lua
    255 return {
    256     name = "keyexchange",
    257     developer = "mydev",
    258     version = "1.0.0",
    259     entry = "src/init.lua",
    260     mode = "cli",
    261     permissions = {"stdio", "import", "run"}
    262 }
    263 
    264 -- com.mydev.keyexchange/src/init.lua
    265 run("crypto")
    266 local crypto = apps["com.luajitos.crypto"]:call("crypto")
    267 
    268 local function toHex(data)
    269     local hex = ""
    270     for i = 1, #data do
    271         hex = hex .. string.format("%02x", string.byte(data, i))
    272     end
    273     return hex
    274 end
    275 
    276 print("X25519 Diffie-Hellman Key Exchange Demo")
    277 print("")
    278 
    279 -- Alice generates her keypair
    280 print("Alice generates keypair...")
    281 local alice_pub, alice_priv = crypto.keyExchange.X25519.keypair()
    282 print("Alice's public key:  " .. toHex(alice_pub))
    283 print("Alice's private key: " .. toHex(alice_priv):sub(1, 32) .. "...")
    284 print("")
    285 
    286 -- Bob generates his keypair
    287 print("Bob generates keypair...")
    288 local bob_pub, bob_priv = crypto.keyExchange.X25519.keypair()
    289 print("Bob's public key:  " .. toHex(bob_pub))
    290 print("Bob's private key: " .. toHex(bob_priv):sub(1, 32) .. "...")
    291 print("")
    292 
    293 -- Alice computes shared secret using her private key and Bob's public key
    294 print("Alice computes shared secret...")
    295 local alice_shared = crypto.keyExchange.X25519.sharedSecret(alice_priv, bob_pub)
    296 print("Alice's shared secret: " .. toHex(alice_shared))
    297 print("")
    298 
    299 -- Bob computes shared secret using his private key and Alice's public key
    300 print("Bob computes shared secret...")
    301 local bob_shared = crypto.keyExchange.X25519.sharedSecret(bob_priv, alice_pub)
    302 print("Bob's shared secret:   " .. toHex(bob_shared))
    303 print("")
    304 
    305 -- Verify they match
    306 if alice_shared == bob_shared then
    307     print("✓ Shared secrets match! Secure channel established.")
    308 else
    309     print("✗ Shared secrets don't match! Something went wrong.")
    310 end
    311 ```
    312 
    313 Usage: `keyexchange`
    314 
    315 ## Available Crypto Functions
    316 
    317 Once you import the crypto library, you have access to:
    318 
    319 ### Hashing
    320 - `crypto.MD5(data)` → 16 bytes
    321 - `crypto.SHA1(data)` → 20 bytes
    322 - `crypto.SHA256(data)` → 32 bytes
    323 - `crypto.SHA512(data)` → 64 bytes
    324 - `crypto["SHA3-256"](data)` → 32 bytes
    325 - `crypto["SHA3-512"](data)` → 64 bytes
    326 - `crypto["BLAKE2b-256"](data)` → 32 bytes
    327 - `crypto["BLAKE2b-512"](data)` → 64 bytes
    328 - `crypto.CRC32(data)` → 4 bytes
    329 
    330 ### Key Derivation
    331 - `crypto.PBKDF2(password, salt, iterations, keylen)` → keylen bytes
    332 - `crypto.Argon2id(password, salt)` → 32 bytes
    333 - `crypto.generateSalt()` → 32 bytes
    334 
    335 ### Digital Signatures (Ed25519)
    336 - `crypto.sign.Ed25519.keypair()` → (pubkey, privkey)
    337 - `crypto.sign.Ed25519.sign(data, privkey)` → signature (64 bytes)
    338 - `crypto.sign.Ed25519.verify(data, signature, pubkey)` → boolean
    339 
    340 ### Key Exchange (X25519)
    341 - `crypto.keyExchange.X25519.keypair()` → (pubkey, privkey)
    342 - `crypto.keyExchange.X25519.publicKey(privkey)` → pubkey
    343 - `crypto.keyExchange.X25519.sharedSecret(privkey, pubkey)` → shared_secret (32 bytes)
    344 
    345 ### Random Generation
    346 - `crypto.random(bytes)` → random data
    347 - `crypto.newKey(bytes)` → random key
    348 
    349 ## Helper Functions
    350 
    351 You'll often need these helper functions to convert between binary and hex:
    352 
    353 ```lua
    354 -- Convert binary data to hex string
    355 local function toHex(data)
    356     if not data then return "nil" end
    357     local hex = ""
    358     for i = 1, #data do
    359         hex = hex .. string.format("%02x", string.byte(data, i))
    360     end
    361     return hex
    362 end
    363 
    364 -- Convert hex string to binary data
    365 local function fromHex(hex)
    366     if not hex then return nil end
    367     hex = hex:gsub("%s+", "")  -- Remove whitespace
    368     if #hex % 2 ~= 0 then
    369         return nil, "Hex string must have even length"
    370     end
    371     local binary = ""
    372     for i = 1, #hex, 2 do
    373         local byte = tonumber(hex:sub(i, i+1), 16)
    374         if not byte then
    375             return nil, "Invalid hex character at position " .. i
    376         end
    377         binary = binary .. string.char(byte)
    378     end
    379     return binary
    380 end
    381 ```
    382 
    383 ## Best Practices
    384 
    385 1. **Always check if import succeeded**
    386    ```lua
    387    local crypto = apps["com.luajitos.crypto"]:call("crypto")
    388    if not crypto then
    389        print("Error: Failed to import crypto")
    390        return
    391    end
    392    ```
    393 
    394 2. **Store keys securely**
    395    - Use the filesystem permission to save keys to `$/data/`
    396    - Never hardcode keys in your source code
    397    - Use proper key derivation (PBKDF2/Argon2id) for passwords
    398 
    399 3. **Use appropriate hash functions**
    400    - **Passwords**: Use PBKDF2 or Argon2id (with salt and high iterations)
    401    - **File integrity**: Use SHA256 or BLAKE2b
    402    - **Quick checksums**: Use CRC32 (not cryptographically secure)
    403 
    404 4. **Handle binary data correctly**
    405    - All crypto functions return binary data
    406    - Use `toHex()` or base64 encoding for storage/display
    407    - Use `fromHex()` or base64 decoding when loading keys
    408 
    409 5. **Understand key sizes**
    410    - Ed25519: 32-byte public key, 64-byte private key
    411    - X25519: 32-byte keys
    412    - PBKDF2/Argon2id: Configurable output length
    413    - Random/keys: Specify desired byte count
    414 
    415 ## Troubleshooting
    416 
    417 ### "Error: crypto app not found"
    418 - Make sure you have the `run` permission in your manifest
    419 - The crypto app must be installed at `/apps/com.luajitos.crypto/`
    420 
    421 ### "Error: failed to import crypto library"
    422 - Make sure you have the `import` permission in your manifest
    423 - Ensure you ran `run("crypto")` before trying to import
    424 
    425 ### "Attempt to access undefined global: crypto"
    426 - The crypto library must be imported, it's not automatically available
    427 - Follow the import steps above
    428 
    429 ### Binary data looks garbled
    430 - Crypto functions return binary data, not strings
    431 - Always use `toHex()` or base64 encoding to display binary data
    432 
    433 ## Notes
    434 
    435 - The crypto library is already available globally in the sandbox, but importing via the crypto app provides a consistent interface
    436 - All cryptographic operations are performed in C for performance
    437 - The import mechanism ensures the crypto app is loaded before use
    438 - Multiple apps can import crypto simultaneously without conflicts