Captcha de coinhive en PHP: alternativa a recaptcha

Introducción

Actualización marzo del 2019: coinhive ha dejado de funcionar o dejará de funcionar al momento de escribir este post; por lo tanto este captcha ya no es válido.

Nota: si quieres usar reCAPTCHA en PHP mira mi otro post. Sé que este post es sobre una alternativa a reCAPTCHA pero como puedes ver, ya no funciona.

Sordid details following…

Un captcha funciona principalmente para detener a los bots y dejar pasar a los humanos. Veamos cómo trabajar con el captcha de coinhive en PHP.

El captcha de coinhive es un captcha como el recaptcha de Google, pero éste funciona minando criptomonedas. Así, no medimos si se trata de una persona o de un bot, sino del poder computacional.

Gracias a esto, a los “spammers” no les funcionará programar bots, pues aunque el captcha no ofrece retos para los bots, hace que la computadora tenga que trabajar. De esta forma los bots tendrán que esperar bastante tiempo antes de hacer lo que iban a hacer.

Cómo implementar captcha de coinhive en PHP

Esto es muy sencillo. Lo que tenemos que hacer es poner el captcha dentro de un formulario. Cuando el captcha detecta que has resuelto los hashes correspondientes, inyecta un nuevo campo al formulario, el cual tiene un token.

Del lado del servidor comprobamos el token con la API de coinhive, y si ambos coinciden entonces significa que el captcha ha sido resuelto correctamente.

Lado del cliente

Comencemos programando el lado del cliente para trabajar con el captcha de coinhive en PHP.

Pongamos de ejemplo este formulario en donde simplemente pedimos un nombre:

<form method="post" action="comprobar.php">
<input type="text" name="nombre" placeholder="Escribe tu nombre">
<input type="submit" value="Enviar">
</form>

Ahora, para integrar el captcha ponemos dentro de él la carga del script y el siguiente div:

<script src="https://authedmine.com/lib/captcha.min.js" async></script>
 <div
            data-disable-elements="[type='submit']"
            data-whitelabel="true"
            class="coinhive-captcha"
            data-hashes="1024"
            data-key="clave">
        <div>
            Esto se muestra mientras el captcha carga
        </div>
    </div>

Expliquemos los atributos:

  • data-disable-elements: un selector css. Todos los elementos que cumplan esa regla serán deshabilitados hasta que los hashes sean completados. Es opcional y sólo ayuda visualmente
  • data-whitelabel: ocultar el logotipo y otras cosas de coinhive
  • class: bueno, esto es una clase. Pero no debemos removerla, me parece que el script toma esa clase como guía para saber en dónde inyectar el captcha
  • data-hashes: cuántos hashes se deben calcular antes de que el captcha sea resuelto. Debe ser un múltiplo de 256. Este valor lo ponemos aquí y también del lado del servidor
  • data-key: nuestra clave pública que obtenemos en el escritorio de coinhive

La lista completa así como la guía la podemos ver en: https://coinhive.com/documentation/captcha

Es importante notar que si el usuario tiene un bloqueador de publicidad el script no se cargará, y por lo tanto no será posible resolver el captcha.

De tal manera que nuestro formulario completo lucirá así (por favor ignorar los estilos por ahora, pues el objetivo del post no es ese):

<form method="post" action="comprobar.php">
	<input type="text" name="nombre" placeholder="Escribe tu nombre">
	<br>
	<br>
 
	<script src="https://authedmine.com/lib/captcha.min.js" async></script>
	<div
	    data-disable-elements="[type='submit']"
	    data-whitelabel="true"
	    class="coinhive-captcha"
	    data-hashes="1024"
	    data-key="clave">
	    <div>
	        Esto se muestra mientras el captcha carga
	    </div>
	</div>
 
	<br>
	<input type="submit" value="Enviar">
 
</form>

Veamos ahora el lado del servidor.

Lado del servidor

Sigamos ahora con el lado del servidor para trabajar con el captcha de coinhive en PHP.

En el lado del servidor recibiremos el nombre y el token. Como lo dije, se enviará por el método post y podremos acceder a él a través de $_POST["coinhive-captcha-token"].

El código de ejemplo queda así:

<?php
$datos = [
    'secret' => 'clave_privada', # clave privada. Obtener de coinhive
    'token' => isset($_POST["coinhive-captcha-token"]) ? $_POST["coinhive-captcha-token"] : "", # el valor que recibimos del formulario. Poner modo por defecto si no lo mandan
    'hashes' => 1024, # el mismo número que pusimos en el formulario
];
 
$contexto = stream_context_create([
    'http' => [
        'header' => "Content-type: application/x-www-form-urlencoded\r\n", #Encabezados, dejar así
        'method' => 'POST', # El método
        'content' => http_build_query($datos) # Formamos la cadena de datos a enviar
    ]
]);
 
$url = 'https://api.coinhive.com/token/verify'; #Aquí se envían las peticiones
$respuesta = json_decode(file_get_contents($url, false, $contexto)); # Hacemos la petición POST
 
/*
    La API devuelve un JSON. Lo decodificamos con json_decode y vemos si 
    no es NULL y si tiene una propiedad llamada success con el valor
    true. En caso de que sí, adelante, el usuario ha
    resuelto el captcha.
    Si no (ya sea porque no se esperó, envió el formulario antes o 
    no resolvió los hashes esperados) entonces no lo dejamos pasar
*/
if($respuesta && $respuesta->success){
    echo "Ok, pasa " . $_POST["nombre"]; #Ejemplo de lo que hacemos si todo va bien
}else{
    echo "¡Alto ahí rufián!"
}
?>

Lo que hacemos es hacer una petición post con stream_context_create. Le pasamos nuestra clave privada (no la pública, ya que la pública va en el formulario), los hashes que pusimos del lado del cliente para evitar trampas y también el token que debió ser generado por el captcha.

De ahí coinhive se encarga de realizar la validación y dependiendo de ello nosotros realizamos acciones.

Obviamente este es un ejemplo básico, no hay validaciones ni estilos, pero muestra lo más importante de cómo trabajar con este servicio que algunos llaman malware aunque no lo es 😉

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.

8 comentarios en “Captcha de coinhive en PHP: alternativa a recaptcha”

  1. Pingback: WebAssembly: definición, usos, ventajas y desventajas - Parzibyte's blog

    1. El resultado es el mismo, incluso con cero, tarda menos , pero tarda mucho todavía y corro el riesgo de que el usuario se desespere y se vaya.

    2. Tienes razón, el usuario puede abandonar la página. Recuerda que únicamente es una alternativa, de ahí puedes seguir usando recaptcha. Por otro lado, te digo de nuevo que depende de la computadora del usuario, prueba en otra PC y verás.

    3. Gracias, hice la prueba en otra computadora con mayor capacidad y ahora tardó unos 30 segundos contra como 5 minutos en la anterior, veo que esto no es viable para equipos con pocas prestaciones, seguiré con recaptcha mejor, saludos.

    4. Sí, te digo que depende mucho de la computadora. En mi caso la mía (y no es nada potente, sirve para lo básico) tarda como 32 segundos para calcular 1024 hashes.

  2. Pingback: API para acortar enlaces con Coinhive en PHP - Parzibyte's blog

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *