Rat
Rat

Reputation: 309

How do I generate a self-signed certificate using PHP and OpenSSL

I'm trying to make a site that generates a self signed certificate using PHP and openSSL. I'm pretty sure it's some sort of syntax error but I cannot seem to find it.

I've tried the command in the linux terminal and it seems to work, but only in the PHP file, it doesn't work.

This is work.php, it is mainly the function:

<?php

function terminal($command)
{
        //system
        if(function_exists('system'))
        {
                ob_start();
                system($command , $return_var);
                $output = ob_get_contents();
                ob_end_clean();
        }
        //passthru
        else if(function_exists('passthru'))
        {
                ob_start();
                passthru($command , $return_var);
                $output = ob_get_contents();
                ob_end_clean();
        }

        //exec
        else if(function_exists('exec'))
        {
                exec($command , $output , $return_var);
                $output = implode(n , $output);
        }

        //shell_exec
        else if(function_exists('shell_exec'))
        {
                $output = shell_exec($command) ;
        }

        else
        {
                $output = 'Command execution not possible on this system';
                $return_var = 1;
        }

        return array('output' => $output , 'status' => $return_var);
}

?>

And this is index.php which is the main file

<form method="post">
<input type="text" placeholder="domain" name="name"></input>
<input type="submit" value="submit" name="submit"></input>
</form>
<?php

if(isset($_POST['submit']))
{
   $name = $_POST["name"];
   run();
}

function run() {
require "work.php";
$status = 0;
$name = $_POST["name"];


$command1 = "openssl req -x509 -newkey rsa:4096 -nodes -keyout " . $name . ".key -out " . $name . ".pem -days 3650 -subj '/CN=" . $name . "'";
$o = terminal($command1);

echo $o['output'];
echo "<br><br>";
echo "Your certificate >> <a href='" . $name . ".pem'>DOWNLOAD</a>";
echo "<br>";
echo "Your private key >> <a href='" . $name . ".key'>DOWNLOAD</a>";

}

?>

Upvotes: 1

Views: 6606

Answers (1)

Professor Abronsius
Professor Abronsius

Reputation: 33813

as example how one might potentially generate certificates using native php functions rather than executing a string command

<?php
    error_reporting( E_ALL );
    $result=false;



    /* 
        configure as appropriate - the root directory
        for all web data
    */
    $rootdir='c:\wwwroot';
    /*
        an aliased directory within web root - select
        an appropriate path
    */
    $certdir=$rootdir . '\content\stack';
    /* 
        to aid correct display of hyperlinks for my environment
        which uses aliases and symbolic links so probably not
        required otherwise
    */
    $displaypath=dirname( $_SERVER['REQUEST_URI'] );






    if( $_SERVER['REQUEST_METHOD']=='POST' && !empty( $_POST['name'] ) ){


        $name=filter_input( INPUT_POST, 'name', FILTER_SANITIZE_STRING );


        if( $name ){



            function create( $rootdir='c:/wwwroot', $certdir=false, $certname='certificate', $dn=array(), $passphrase=null, $createpem=true, $overwrite=true ){
                if( !empty( $certdir ) && !empty( $certname ) && !empty( $dn ) ){

                    $out = new stdClass;
                    $days = 3650;

                    /* !!! configuration and location of your own openssl.conf file is important !!! */
                    putenv( sprintf( 'OPENSSL_CONF=%s/openssl.cnf', $rootdir ) );

                    $config=array(
                        'config'            =>  getenv('OPENSSL_CONF'),
                        'digest_alg'        =>  'AES-128-CBC',
                        'private_key_bits'  =>  4096,
                        'private_key_type'  =>  OPENSSL_KEYTYPE_RSA,
                        'encrypt_key'       =>  false
                    );

                    /*
                        Primary configuration is overwritten at runtime
                        by including parameters in the "$dn" argument
                    */
                    $dn=array_merge( array(
                        "countryName"               => "UK",
                        "stateOrProvinceName"       => "Strathclyde",
                        "localityName"              => "Scotland",
                        "organizationName"          => "bonny-scotland.org",
                        "organizationalUnitName"    => "Bonny Scotland",
                        "commonName"                => $certname,
                        "emailAddress"              => "[email protected]"
                    ), $dn );

                    $privkey = openssl_pkey_new( $config );
                    $csr = openssl_csr_new( $dn, $privkey, $config );
                    $cert = openssl_csr_sign( $csr, null, $privkey, $days, $config, 0 );

                    openssl_x509_export( $cert, $out->pub );
                    openssl_pkey_export( $privkey, $out->priv, $passphrase );
                    openssl_csr_export( $csr, $out->csr );



                    # Create the base private & public directories if they do not exist
                    $privdir = $certdir . sprintf('\\certificates\\%s\\private\\',$certname );
                    $pubdir  = $certdir . sprintf('\\certificates\\%s\\public\\',$certname );

                    @mkdir( $privdir, 0777, true );
                    @mkdir( $pubdir, 0777, true );


                    $pkpath=$privdir . $certname . '.key';
                    $cert=$pubdir . $certname . '.crt';
                    $csr=$privdir . $certname . '.csr';
                    $pem=$pubdir . $certname . '.pem';


                    if( !file_exists( $pkpath ) or ( $overwrite==true && file_exists( $pkpath ) ) ) {

                        openssl_pkey_export_to_file( $privkey, $pkpath, $passphrase, $config );

                        file_put_contents( $cert, $out->pub, FILE_TEXT );
                        file_put_contents( $csr, $out->csr, FILE_TEXT );

                        if( $createpem ){
                            unset( $out->csr );
                            file_put_contents( $pem, implode( '', get_object_vars( $out ) ) );
                        }
                    }
                    openssl_pkey_free( $privkey );
                    clearstatcache();

                    /* return useful stuff for display porpoises */
                    return (object)array(
                        'public'        =>  str_replace( $certdir, '', $pubdir ),
                        'private'       =>  str_replace( $certdir, '', $privdir ),
                        'pubsize'       =>  filesize( $pem ),
                        'privsize'      =>  filesize( $pkpath ),
                        'pkpath'        =>  $pkpath,
                        'cert'          =>  $cert,
                        'csr'           =>  $csr,
                        'pem'           =>  $pem,
                        'certificate'   =>  $certname
                    );
                }
                return false;
            }



            /* configure the DN array */
            $dn=array(
                'countryName'               =>  'GB',
                'localityName'              =>  'England',
                'stateOrProvinceName'       =>  'London',
                'organizationName'          =>  $name,
                'organizationalUnitName'    =>  'Squirrel Juggling Services',
                'emailAddress'              =>  sprintf( 'admin-contact@%s', $name )
            );
            $result=create( $rootdir, $certdir, $name, $dn );
        }
    }
?>
<!DOCTYPE html>
<html lang='en'>
    <head>
        <meta charset='utf-8' />
        <title>Generate Certificates</title>
        <style>
            body,body *{box-sizing:border-box;font-family:calibri,verdana,arial;}
            body{ background:white; width:100%; height:100vh;margin:0;display:flex;flex-direction:column; align-content:center; justify-content:center; align-items:center;}
            form{ border:1px solid rgba(0,0,0,0.25); border-radius:1rem; background:whitesmoke; padding:1rem;width:30%; height:auto; min-height:250px; display:flex; flex-direction:column; align-content:center; justify-content:center; align-items:center; }
            form *{align-self:stretch;flex:1;margin:0.5rem;}
            [type='text']{text-align:center;}
            h1{font-size:1.45rem;text-align:center}
            h2{font-size:1.15rem;text-align:center}
        </style>
    </head>
    <body>
        <form method='post'>
            <h1>Generate Self-Signed SSL Certificate</h1>
            <input type='text' name='name' placeholder='domain' />
            <input type='submit' />
        </form>
        <?php
            if( $_SERVER['REQUEST_METHOD']=='POST' && is_object( $result ) ){
                printf(
                    '
                    <h2>Certificate for "%s" generated successfully!</h2>
                    <a href="%s" target="_blank">Download Public Certificate ( %s Kb )</a>
                    <a href="%s" target="_blank">Download Private Key ( %s Kb )</a>',

                    $result->certificate,
                    sprintf( '%s%s%s.pem', $displaypath, $result->public, $result->certificate ),
                    round( ( $result->pubsize / 1024 ), 2 ),
                    sprintf( '%s%s%s.key', $displaypath, $result->private, $result->certificate ),
                    round( ( $result->privsize / 1024 ), 2 )
                );
            }
        ?>
    </body>
</html>

Upvotes: 5

Related Questions