package com.secureline.server;

import android.util.Slog;

import org.json.JSONObject;

import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.X509EncodedKeySpec;

public class SecureLineLicenseVerifier {

    private static final String TAG =
            "SecureLineLicenseVerifier";

    private static final String SERVER_PUBLIC_KEY_HEX =
    "3059301306072a8648ce3d020106082a8648ce3d0301070342000415a371e7e53dbb92df8c4432dcc4533aeb5476f60e54b98a0f158a6303b5bd4556a326a7a4684e0c2756ac58833feef7b0e1139505fa8897f00fd51f1dea1f36";

    private final PublicKey mServerKey;

    public SecureLineLicenseVerifier() {

        try {

            byte[] der =
                    hexToBytes(
                            SERVER_PUBLIC_KEY_HEX
                    );

            mServerKey =
                    KeyFactory
                            .getInstance("EC")
                            .generatePublic(
                                    new X509EncodedKeySpec(
                                            der
                                    )
                            );

        } catch (Exception e) {

            throw new RuntimeException(
                    "License public key load failed",
                    e
            );
        }
    }

    public JSONObject verify(

            String payloadBase64,
            String signatureBase64,
            String expectedDeviceId

    ) throws Exception {

        byte[] payload =
                android.util.Base64.decode(
                        payloadBase64,
                        android.util.Base64.URL_SAFE
                                | android.util.Base64.NO_WRAP
                );

        byte[] signature =
                android.util.Base64.decode(
                        signatureBase64,
                        android.util.Base64.URL_SAFE
                                | android.util.Base64.NO_WRAP
                );

        Signature sig =
                Signature.getInstance(
                        "SHA256withECDSA"
                );

        sig.initVerify(
                mServerKey
        );

        sig.update(
                payload
        );

        if (!sig.verify(signature)) {

            throw new SecurityException(
                    "License signature invalid"
            );
        }

        JSONObject license =
                new JSONObject(

                        new String(
                                payload,
                                StandardCharsets.UTF_8
                        )
                );

        if (!license.getString("device_id")
                .equals(expectedDeviceId)) {

            throw new SecurityException(
                    "License device mismatch"
            );
        }

        Slog.i(

                TAG,

                "License OK counter="

                        +

                        license.getLong(
                                "license_counter"
                        )
        );

        return license;
    }

    private static byte[] hexToBytes(
            String hex
    ) {

        int len =
                hex.length();

        byte[] out =
                new byte[len / 2];

        for (int i = 0;
             i < len;
             i += 2) {

            out[i / 2] =
                    (byte) (

                            (Character.digit(
                                    hex.charAt(i),
                                    16
                            ) << 4)

                                    +

                                    Character.digit(
                                            hex.charAt(i + 1),
                                            16
                                    )

                    );
        }

        return out;
    }
}