"use strict";
/*
The stucture of an ADB RSAPublicKey is as follows:

    #define RSANUMBYTES 256           // 2048 bit key length
    #define RSANUMWORDS (RSANUMBYTES / sizeof(uint32_t))

    typedef struct RSAPublicKey {
        int len;                  // Length of n[] in number of uint32_t
        uint32_t n0inv;           // -1 / n[0] mod 2^32
        uint32_t n[RSANUMWORDS];  // modulus as little endian array
        uint32_t rr[RSANUMWORDS]; // R^2 as little endian array
        int exponent;             // 3 or 65537
    } RSAPublicKey;

 */
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const node_forge_1 = __importDefault(require("node-forge"));
const bluebird_1 = __importDefault(require("bluebird"));
const BigInteger = node_forge_1.default.jsbn.BigInteger;
class Auth {
    static parsePublicKey(buffer) {
        return new bluebird_1.default(function (resolve, reject) {
            const match = Auth.RE.exec(buffer);
            if (match) {
                const struct = Buffer.from(match[1], 'base64');
                const comment = match[2].trim();
                return resolve(Auth.readPublicKeyFromStruct(struct, comment));
            }
            else {
                return reject(new Error('Unrecognizable public key format'));
            }
        });
    }
    static readPublicKeyFromStruct(struct, comment) {
        if (!struct.length) {
            throw new Error('Invalid public key');
        }
        // Keep track of what we've read already
        let offset = 0;
        // Get len
        const len = struct.readUInt32LE(offset) * 4;
        offset += 4;
        if (struct.length !== 4 + 4 + len + len + 4) {
            throw new Error('Invalid public key');
        }
        // Skip n0inv, we don't need it
        offset += 4;
        // Get n
        const n = Buffer.alloc(len);
        struct.copy(n, 0, offset, offset + len);
        [].reverse.call(n);
        offset += len;
        // Skip rr, we don't need it
        offset += len;
        // Get e
        const e = struct.readUInt32LE(offset);
        if (!(e === 3 || e === 65537)) {
            throw new Error(`Invalid exponent ${e}, only 3 and 65537 are supported`);
        }
        // FIXME: bug in @types/node-forge
        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
        // @ts-ignore
        const modulus = new BigInteger(n.toString('hex'), 16);
        // FIXME: bug in @types/node-forge
        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
        // @ts-ignore
        const exponent = new BigInteger(e.toString(), 10);
        // Restore the public key
        const key = node_forge_1.default.pki.rsa.setPublicKey(modulus, exponent);
        // It will be difficult to retrieve the fingerprint later as it's based
        // on the complete struct data, so let's just extend the key with it.
        const md = node_forge_1.default.md.md5.create();
        md.update(struct.toString('binary'));
        const extendedKey = key;
        extendedKey.fingerprint = md.digest().toHex().match(/../g).join(':');
        // Expose comment for the same reason
        extendedKey.comment = comment;
        return extendedKey;
    }
}
Auth.RE = /^((?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?)\0?( .*|)\s*$/;
exports.default = Auth;
//# sourceMappingURL=auth.js.map