Chapter 4. Miscellaneous Cryptography
Prev |  | Next

## Chapter 4. Miscellaneous Cryptography

## 4.1. Crypt_Hash

### 4.1.1. Supported Algorithms and Dependencies

The following algorithms are supported:

md2, md5, md5-96, sha1, sha1-96, sha256, sha384, and sha512

Crypt_Hash requires, minimally, PHP 4.3.0 (due to its use of sha1()). If sha384 or sha512 are being used and you're not running PHP 5.1.2 or greater then Math/BigInteger.php is also required.

Crypt_Hash uses the hash extension if it's available (> 5.1.2), mhash if it's not, and it's own internal implementation if not even mhash is available.

### 4.1.2. Example

    <?php
    include('Crypt/Hash.php');

    $hash = new Crypt_Hash('sha1');
    //$hash->setKey('abcdefg');
    echo bin2hex($hash->hash('abcdefg'));
    ?>

If `$hash->setKey()` had been called `$hash->hash()` would have returned an HMAC.

## 4.2. Crypt_RSA

### 4.2.1. Dependencies

If you're running PHP 5, Crypt_RSA requires Math/BigInteger.php and Crypt/Hash.php. If you're running PHP 4, Crypt_RSA also requires PHP/Compat/Function/array_fill.php, PHP/Compat/Function/bcpowmod.php, and PHP/Compat/Function/str_split.php

### 4.2.2. Examples

Here's an example of how to encrypt / decrypt with Crypt_RSA:

    <?php
    include('Crypt/RSA.php');

    $rsa = new Crypt_RSA();
    extract($rsa->createKey());

    $plaintext = 'terrafrost';

    $rsa->loadKey($privatekey);
    $ciphertext = $rsa->encrypt($plaintext);

    $rsa->loadKey($publickey);
    echo $rsa->decrypt($ciphertext);
    ?>

Here's an example of how to create / verify a signature with Crypt_RSA:

    <?php
    include('Crypt/RSA.php');

    $rsa = new Crypt_RSA();
    extract($rsa->createKey());

    $plaintext = 'terrafrost';

    $rsa->loadKey($privatekey);
    $signature = $rsa->sign($plaintext);

    $rsa->loadKey($publickey);
    echo $rsa->verify($plaintext, $signature) ? 'verified' : 'unverified';
    >

### 4.2.3. createKey()

`createKey()` takes three parameters - `$bits`, `$timeout`, and `$primes`. `$timeout` is present since creating a key has the potential to be fairly time consuming and will guarantee that `createKey()` does not run for more than `$timeout` seconds. `$primes` lets provide pre-computed prime numbers to speed things up.

`extract($rsa->createKey())` creates three variables - `$publickey`, `$privatekey`, and `$partialkey`. If `createKey` hit the timeout then it'll return all the primes that it had managed to compute so that you might pass them back to `createKey()` on a subsequent call.

The exponent can be set by defining `CRYPT_RSA_EXPONENT` and multi-prime RSA can be utilized by adjusting `CRYPT_RSA_SMALLEST_PRIME`. Note that these must be done before a Crypt_RSA() object is initialized.

Smaller values for `CRYPT_RSA_SMALLEST_PRIME` result in increased speed at the cost of security.

### 4.2.4. setPrivateKeyFormat(), setPublicKeyFormat(), loadKey() and setPassword()

Crypt_RSA supports the following formats:

CRYPT_RSA_PRIVATE_FORMAT_PKCS1:

    -----BEGIN RSA PRIVATE KEY-----
    MIICWgIBAAKBgHx5XHa3LjiugtNq2xkd0oFf2SdsJ04hQYLoeRR3bqAei3Gc+PSy
    AvynCIh/03JCvBsUHaCe8BwjwaTYrpq5QunGo/wvIzvx2d3G9dlrpOIFLiatZYOf
    h07+CkSfaRXhBUKkul/gU87WPhKEcbnPDJS10uD1HqLsHfSKLNitGOf7AgElAoGA
    ENIhQHmedlzFkjEI2eFveURNxw6dhxlANEjtxH7XmRjiaUyQWGsVKQ+nNQpa2Bbb
    JkD9FbSc/OI8wz/gPmwP9eJN29CriebhaV3ebM1L1gbb5r7Vf/D/6rxB0BG/h2lA
    jyZWEZrV/Gi9ZCaw/J+IUu1pAskKid84yHphvszywCUCQQDigrtr+cVkwkUsxOGd
    B378yQCroXmybAD7FQHwVslafuFfTHkaMQSU/ZZLVY1ioMs1VVzzq/vOu0RstZOY
    AfHFAkEAjK3mIWdG4JOM44/SrDkACNatsMtXKOi4K3SlXu9ie6ikXPD+GSZ+bWCX
    GstFaXr9cHRvZPF3qYtK+j2N9UXOvwJBALeoRO/DmSFDkgifoixLRF5CHDgiD6Vs
    U9J/vGIBLaNSHoSe3rtKVr3+CyhTNF3Oe0AABi1bA4UGioGn+yFNr0UCQBbQF3sJ
    1CRq9ECT3PlVWfOYbzFtFQ2NhaYul1uAw9yzkEZsROF73SZ+XbFRZTOzFFds08su
    E2eaDCiUXDWcnhECQQCRUQn2huHlssj8kt35NAVwiHCNfaeSQ5tiDcwfOywA4YXl
    Q+kpuWq5U3V8j/9/n7pE/DL0nXEG/3QpKHJEYV5T
    -----END RSA PRIVATE KEY-----

CRYPT_RSA_PRIVATE_FORMAT_PKCS1 (with password):

    -----BEGIN RSA PRIVATE KEY-----
    Proc-Type: 4,ENCRYPTED
    DEK-Info: DES-EDE3-CBC,0AE1DB47E71463BE

    pI2Kk5ceURbMYNo1xQqqA5rm2/QP4hgj/HuvrACtPSz/aesbG+h4lYXGpQ9os6Ha
    AyFW+iX2UWS6BRwJj1ztO20sKT6ckg7eINSfiSSAeOOiG5aHLxOYayO9aQ5UrrJX
    r0QmwRJRiHTW/82PLBNzfFHYskslNI9EWA5L/Gg4NAXDWwDooGvGkDq3ex7WkWLr
    k7DN2JoZuWsUZxwpgTDouRQMsygrsdSjwRDSgbnTn6luEBrL9fc5/oAWf0xoTk5h
    XMiOOHPBNPiZ1883ayq91HL/6895g8U9oIR1wQmdl0USViYYp5jI19ueowCyblzP
    xD3Bfpb6RPaZ/yqECOysPk6PDz257SGDMNk/QrQJ/eZkeniNXHJ8d+nJGuajZeBu
    6A/bglvKGNNNWe8UJMb5P2OAliD7y7F9wXrkV5FnQ/Q49tGxdBl7WXNuGp4x2d9s
    ZEnv3mOtrr1lM+2QE0Zg8mjqSem5b6Dp0LxOj5j45j5IbBrrd3MKu87jJVzp8yHy
    sBC6NMYYtO03qxV/j1kJR+MmAcCF1+4GGRWdFcoc0sXGVqmEOmK4QfYx3T0Vb6Hk
    oLdlh6ofZogezzJ8A1BvV382sTsJ90eqbgz3E+fDl8iR86+EV9bUujFE4IaBgZJP
    gxikVItdTcq1frNKTCSH/RPeRwk+oKWTpCYGgNA+bl641onW1DCLYcd14N6TDKmY
    77cOTf2ZDGOYNPycAF/FnNJJyLO3IYpU63aKBshB4dYeVrfH0FvG6g5Xt0geIkiD
    5W9El4ks7/3r97x443SagDRt6Mceo5TtzzFfAo7cZeA=
    -----END RSA PRIVATE KEY-----

CRYPT_RSA_PRIVATE_FORMAT_PUTTY:

As utilized by PuTTY.

    PuTTY-User-Key-File-2: ssh-rsa
    Encryption: none
    Comment: imported-openssh-key
    Public-Lines: 4
    AAAAB3NzaC1yc2EAAAABJQAAAIB8eVx2ty44roLTatsZHdKBX9knbCdOIUGC6HkU
    d26gHotxnPj0sgL8pwiIf9NyQrwbFB2gnvAcI8Gk2K6auULpxqP8LyM78dndxvXZ
    a6TiBS4mrWWDn4dO/gpEn2kV4QVCpLpf4FPO1j4ShHG5zwyUtdLg9R6i7B30iizY
    rRjn+w==
    Private-Lines: 8
    AAAAgBDSIUB5nnZcxZIxCNnhb3lETccOnYcZQDRI7cR+15kY4mlMkFhrFSkPpzUK
    WtgW2yZA/RW0nPziPMM/4D5sD/XiTdvQq4nm4Wld3mzNS9YG2+a+1X/w/+q8QdAR
    v4dpQI8mVhGa1fxovWQmsPyfiFLtaQLJConfOMh6Yb7M8sAlAAAAQQDigrtr+cVk
    wkUsxOGdB378yQCroXmybAD7FQHwVslafuFfTHkaMQSU/ZZLVY1ioMs1VVzzq/vO
    u0RstZOYAfHFAAAAQQCMreYhZ0bgk4zjj9KsOQAI1q2wy1co6LgrdKVe72J7qKRc
    8P4ZJn5tYJcay0Vpev1wdG9k8Xepi0r6PY31Rc6/AAAAQQCRUQn2huHlssj8kt35
    NAVwiHCNfaeSQ5tiDcwfOywA4YXlQ+kpuWq5U3V8j/9/n7pE/DL0nXEG/3QpKHJE
    YV5T
    Private-MAC: 00d7af96bd88ff8a4ddf4a125b16f83ff2d76091

CRYPT_RSA_PRIVATE_FORMAT_XML:

As specified in the XML Signature standards.

    <RSAKeyValue>
      <Modulus>
        2xrDz/SAJ9QX4qtgnN2E8UlUa5ayPFVhzlv5afeHRL4RDsoqxSDCfL+oZxnZCWAM
        BNwHeFxcaibhfgG3oXbis8yg5yc5ac22zg26S3fcGaz//LXhG+pApHz/Bt6x7SYe
        AeZqm9Bpc1dNAOlCRXd/88Q9405s8q1cfqQzM+gU2Dk=
      </Modulus>
      <Exponent>AQAB</Exponent>
      <P>
        787qpkCapSXhyqks50GHIlnyWL2QGcPHtOhWBmLiOYod1EjrYKM7w5AMN251b+Q/
        hv4Injbc3LbZzCo49J/75Q==</P>
      <Q>
        6eX8GJx/9vv8LHwqQEVrYTcAl2uP+4dUkQCCNWTvJoAY2W3LuG8oPbqPzoDLlj/9
        581xgnI57jkV1g7g/2HtxQ==
      </Q>
      <DP>
        Xe0YgReKuqaUwnDysn069ZxvTIyq1TyWiuf5UbUHUGwldNE+x/IHZXiVIFz2SGYI
        79GuBHIOnbBMrCfZeQ70dQ==
      </DP>
      <DQ>
        eyD66OnZ42cbhT+H7nWc5XxS72NMVJkVR5AA+6K60oW0jyFhkSHTCUvg0FC028+sF
        g7spkMDhAjBGgKTJ12iEQ==
      </DQ>
      <InverseQ>
        50MjKmCl9DZjequHmfW3PZ0cwcTLjhakx1qTcl/Xur0SzgdsIW3ncKJVbG7vfpRl
        HfpH2uNGL7lR66NAj/qI+A==
      </InverseQ>
      <D>
        RiTibU/0O0v+PZXp/y434ls8iJkdBI29Gyh8x7zz9ED5CwgT+zoKqY9eJWuz/Plf
        v6qFRbYj6+P4qrN4C1wZJSkE/vhqHPxdlyNTmoehS0FLiBBhX2EFHg+srU+ArVWT
        fqrvhJhhacp6R7wzFqgH2W6vixaYrmtln77dR7PI39E=
      </D>
    </RSAKeyValue>

CRYPT_RSA_PUBLIC_FORMAT_PKCS1:

    -----BEGIN PUBLIC KEY-----
    MIGGAoGAfHlcdrcuOK6C02rbGR3SgV/ZJ2wnTiFBguh5FHduoB6LcZz49LIC/KcIiH/TckK8GxQd
    oJ7wHCPBpNiumrlC6caj/C8jO/HZ3cb12Wuk4gUuJq1lg5+HTv4KRJ9pFeEFQqS6X+BTztY+EoRx
    uc8MlLXS4PUeouwd9Ios2K0Y5/sCASU=
    -----END PUBLIC KEY-----

CRYPT_RSA_PUBLIC_FORMAT_OPENSSH:

    ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIB8eVx2ty44roLTatsZHdKBX9knbCdOIUGC6HkUd26gHotx
    nPj0sgL8pwiIf9NyQrwbFB2gnvAcI8Gk2K6auULpxqP8LyM78dndxvXZa6TiBS4mrWWDn4dO/gpEn2kV
    4QVCpLpf4FPO1j4ShHG5zwyUtdLg9R6i7B30iizYrRjn+w== phpseclib-generated-key

Passwords can be set via `setPassword()` and are only supported on private keys. CRYPT_RSA_PUBLIC_FORMAT_OPENSSH generates keys that are intended to go in $HOME/.ssh/authorized_keys for use with OpenSSH. Another format - CRYPT_RSA_PUBLIC_FORMAT_RAW - is stored as an array with two indexes - one for the modulus and one for the exponent. Indexes accepted by `loadkey()` are as follows:

e, exponent, publicExponent, modulus, modulo, n

`loadKey()` has two parameters - `$key` and the optional `$type`. The default type, if `$type` is not explicitely set, is CRYPT_RSA_PRIVATE_FORMAT_PKCS1. It should, at this point, be noted that Crypt_RSA treats public and private keys largelly identically. A key can be formatted as a CRYPT_RSA_PUBLIC_FORMAT_PKCS1 and still conform to the CRYPT_RSA_PRIVATE_FORMAT_PKCS1 format and vice versa. The only real difference between private keys and public keys is that private keys *can* contain their public key counterparts whereas public keys cannot. That said, this distinction is, for the most part, irrelevant and academic. For a more thorough discussion of this see setPublicKey() and getPublicKey().

### 4.2.5. setPublicKey() and getPublicKey()

As noted in setPrivateKeyFormat(), setPublicKeyFormat(), loadKey() and setPassword(), Crypt_RSA treats public and private keys largely identically. The only real difference is that some private key formats contain the public key within them whereas no public key format does. The reason you'd want to do this is for indexing purposes. For example, in SSH-2, RSA authentication works by sending your public key along with a signature created by your private key. The SSH-2 server then looks the public key up in an index of public keys to see if it's an allowed key and then verifies the signature. To that end, `setPublicKey()` defines the public key if it hasn't already been defined and `getPublicKey()` returns it. `getPublicKey()` has an optional parameter - $type - that sets the format.

Per the above, 99% of the time, setPublicKey() is not a function you want to be calling. If you want to load a public key, call loadKey(). That function is called loadKey() and not loadPrivateKey() for a reason. If you've been reading the documentation, this should be obvious, but if you're skimming through it it may not be.

### 4.2.6. encrypt(), decrypt() and setEncryptionMode()

Crypt_RSA supports two encryption modes - `CRYPT_RSA_ENCRYPTION_OAEP` and `CRYPT_RSA_ENCRYPTION_PKCS1`. `CRYPT_RSA_ENCRYPTION_OAEP` uses Optimal Asymmetric Encryption Padding and provides more security than `CRYPT_RSA_ENCRYPTION_PKCS1`.

Both `CRYPT_RSA_ENCRYPTION_OAEP` and `CRYPT_RSA_ENCRYPTION_PKCS1` impose limits on how large the plaintext can be. If the plaintext exceeds these limits the plaintext will be split up such that each block falls within those limits.

### 4.2.7. sign(), verify(), and setSignatureMode()

Crypt_RSA supports two signature modes - `CRYPT_RSA_SIGNATURE_PSS` and `CRYPT_RSA_SIGNATURE_PKCS1`. The former is assumed to provide more security than the latter. See Examples for examples.

### 4.2.8. setHash(), setMGFHash() and setSaltLength()

In all likelihood, calling these functions will be unnecessary as the default values should be sufficient. A discussion of them none-the-less follows.

`setHash()` is used with signature production / verification and (if the encryption mode is CRYPT_RSA_ENCRYPTION_OAEP) encryption and decryption. If the specified hash isn't supported sha1 will be used.

`setMGFHash()` determines which hashing function should be used for the mask generation function as utilized in CRYPT_RSA_ENCRYPTION_OAEP and CRYPT_RSA_SIGNATURE_PSS. PKCS#1 recommends but does not require that the MGFHash and the Hash be set to the same thing.

`setSaltLength()` is only utilized with CRYPT_RSA_SIGNATURE_PSS. PKCS#1 recommends this value either be 0 (which is what it is by default) or the length of the output of the hash function as set via `setHash()`

Prev |  | Next
Chapter 3. Symmetric-key Cryptography | Home | Chapter 5. Networking