/iron-crypto-php

PHP implementation of the iron cryptographic utility

Primary LanguagePHPMIT LicenseMIT

Iron Crypto PHP

Version Number PHP Version License

A PHP implementation of the 6.x version of the iron cryptographic utility.

Table of Contents

What is iron?

According to the iron API:

iron is a cryptographic utility for sealing a JSON object using symmetric key encryption with message integrity verification. Or in other words, it lets you encrypt an object, send it around (in cookies, authentication credentials, etc.), then receive it back and decrypt it. The algorithm ensures that the message was not tampered with, and also provides a simple mechanism for password rotation.

iron can be considered as an alternative to JSON Web Tokens (JWT). Check out this iron issue for a small discussion of the difference between iron and JWT.

Note that iron is often spelled in all lowercase letters; however, the i is capitalized in the class names in this package.

Getting Started

Prerequisites

  • Git 2.9+
  • PHP 5.5.0+
  • OpenSSL PHP Extension
  • JSON PHP Extension
  • Composer

Installation

Download and install using Composer:

composer require shawm11/iron-crypto

Usage

Iron vs Iron2 Classes

Either the Iron or Iron2 class can be used to seal or unseal iron strings. The Iron2 class includes a fix for an issue with PDKDF2, so it is a bit more secure than the Iron class. However, the iron strings Iron and Iron2 are not compatible with each other. The MAC format version in the sealed string created using Iron2 is 2.1 instead of 2 to indicate the incompatibility.

iron strings created using the Iron class can be unsealed by other iron implementations and it can unseal iron strings from other implementations. This is not true for the Iron2 class.

In summary, use the Iron2 class (RECOMMENDED) if:

  • you need or want a bit more security
  • compatibility with other iron implementations is not important

and use the Iron class if:

  • unsealing an iron string created by another implementation
  • the sealed iron string created will be unsealed by another implementation

Examples

Examples of Sealed Iron Strings

Array to be sealed:

[
    'a' => 1,
    'b' => 2,
    'c' => [3, 4, 5],
    'd' => [
        'e' => 'f'
    ]
]
Iron2::seal()

Password: some_not_random_password_that_is_at_least_32_characters

Output:

Fe26.2.1**50a5bec38a21775318b487bda8eb5bac8ef0033fa14ab3d7d963643b648fb50a*dZ7cUbgFie4_EKYQ1H1RyA*mclk0QCWDb-irF7E5quIcRa52t4TXmo3Jq1BnJFgVv4dZq9fWnB0CUdRA8bKXIEX**da6bb68d955f9db04e9739a2a197ce9780de56f9be26ba24b7bf145c12851d53*0xYQdFBJxipufS03zBu6VZmIlHClv6CTlCc_To1rbIU
Iron2::seal() with password rotation

Passwords:

[
    "some_not_random_password_that_is_at_least_32_characters1",
    "some_not_random_password_that_is_at_least_32_characters2",
    "some_not_random_password_that_is_at_least_32_characters3" // Chose this one to create output
]

Output:

Fe26.2.1*2*292e8975ab168c4aff5af0674ae7e49f11307a367e75aee7f5f71063d8132523*QkjFNS0jl7963ENLosY25g*uKNcL7JAlDPURnvMb0C_jHyELe0b84554QcYzeaYWiHI1x0Qwq3Njikf_z_iLYxX**18280c5865db88bd915570325c56f8b6897a3daf710d8a9c9330ead5f392ec4d*ogb2rO5-QiOQk28gfpa3p2PimRM5y015C892SQ_c3y8
Iron::seal()

Password: some_not_random_password_that_is_at_least_32_characters

Output:

Fe26.2**6589f8726e6b87f875bd9cbdea1985642d8d2e82168360586cf9cdb46b370fcc*-2XpTXRy5ZL0gJK6Qx9i4Q*hZa7pqt31QIR_ihVZ6qjUv_b0v5KLd1Enhq5q0IjbSfbvnUm_kRDahIC-nAoCsjJ**c74d1c46525da622ddc699c8dabf3902e1f1497bf54e086004fa560d85082e71*1qpfA_ZlR4r5Uo99Py1UU_l7v8lZYjtFI-4QVFYHA1g

Code Example of Common Usage

<?php

// Here Iron2 is used, but this code works the same way with Iron
use Shawm11\Iron\Iron2;
use Shawm11\Iron\IronOptions;
use Shawm11\Iron\IronException;

// This could be some decoded JSON
$obj = [
    'a' => 1,
    'b' => 2,
    'c' => [3, 4, 5],
    'd' => [
        'e' => 'f'
    ]
];
$password = 'some_not_random_password_that_is_at_least_32_characters';
$sealed = '';
$unsealed = [];

// Initialize with the default options
$iron = new Iron2(IronOptions::defaults);

// Seal an array (or a decoded JSON array)
try {
    $sealed = $iron->seal($obj, $password); // Output is a string
    echo $sealed;
} catch (IronException $e) {
    echo 'SEAL ERROR: ' . $e->getMessage();
}

// Unseal an iron-sealed object string, which can be sent via cookies, a URI
// query parameter, or an HTTP header attribute
try {
    $unsealed = $iron->unseal($sealed, $password); // Output is an array
    echo $unsealed;
} catch (IronException $e) {
    echo 'UNSEAL ERROR: ' . $e->getMessage();
}

Password Rotation Code Example

<?php

// Here Iron is used (unlike the previous example), but this code works the same
// way with Iron2
use Shawm11\Iron;
use Shawm11\Iron\IronOptions;
use Shawm11\Iron\IronException;

// This could be some decoded JSON
$obj = [
    'a' => 1,
    'b' => 2,
    'c' => [3, 4, 5],
    'd' => [
        'e' => 'f'
    ]
];

// The password IDs (array keys) for the array of possible passwords can be
// anything as long as they contain only letters, numbers, and underscores.
$possiblePasswords = [
    'a' => 'some_not_random_password_that_is_at_least_32_characters1',
    'b' => 'some_not_random_password_that_is_at_least_32_characters2',
    '0' => 'some_not_random_password_that_is_at_least_32_characters3',
    '1' => 'some_not_random_password_that_is_at_least_32_characters4',
    '_' => 'some_not_random_password_that_is_at_least_32_characters5',
    'Something_different42' => 'some_not_random_password_that_is_at_least_32_characters6',
    // The password with the special name of 'default' will be the password that
    // is used if no password ID is specified in an iron string. In other words,
	// it is the default password.
    'default' => 'some_not_random_password_that_is_at_least_32_characters'
];

$chosenPasswordKey = '1';
$password = [
    'id' => $chosenPasswordKey, // Used to uniquely identify the password
    'secret' => $possiblePasswords[$chosenPasswordKey] // The actual password
];

$sealed = '';
$unsealed = [];

// Initialize with the default options
$iron = new Iron(IronOptions::defaults);

// Seal an array (or decoded JSON array)
try {
    $sealed = $iron->seal($obj, $password); // Output is a string
    echo $sealed;
} catch (IronException $e) {
    echo 'SEAL ERROR: ' . $e->getMessage();
}

// Unseal an iron-sealed object string, which can be sent via cookies, a URI
// query parameter, or an HTTP header attribute
try {
    $unsealed = $iron->unseal($sealed, $possiblePasswords); // Output is an array
    echo $unsealed;
} catch (IronException $e) {
    echo 'UNSEAL ERROR: ' . $e->getMessage();
}

API

See the API Reference for details about the API.

Security Considerations

See the Security Considerations section of iron's API document.

Related Projects

  • Oz PHP Implementation — Oz is a web authorization protocol that is an alternative to OAuth 1.0a and OAuth 2.0 three-legged authorization. Oz utilizes both Hawk and iron.

  • Hawk PHP Implementation — Hawk is an HTTP authentication scheme that is an alternative to OAuth 1.0a and OAuth 2.0 two-legged authentication.

Contributing/Development

Please read CONTRIBUTING.md for details on coding style, Git commit message guidelines, and other development information.

Versioning

This project uses SemVer for versioning. For the versions available, see the tags on this repository.

License

This project is open-sourced software licensed under the MIT license.