Générez vos licences applicatives avec NestJS !

La génération de licence applicative peut être très abstraite, et il n'y a pas énormément de documentation a ce sujet sur le net. Je vais vous montrer comment générer un système de licence applicative basique et simple en quelques minutes avec NestJS !

J'ai récemment été confronté à une problématique sur l'un de mes projets d'application lourde. Celle-ci, développée en ElectronJS et avec un backend en NestJS, devait contenir des fonctionnalités gratuites et payantes. Et afin d'identifier et permettre à un client d'accéder à ces fonctionnalités payantes, je devais alors créer un système de licence applicative.

Prérequis

Pour créer un système basique de génération de licence applicative, vous aurez besoin de la librairie npm crypto et d'un service NestJS a part dans lequel nous allons centraliser tout notre générateur et ses fonctions annexes.

Générer une paire de clé RSA pour chiffrer votre licence

Notre licence se base sur un chiffrement d'informations liées à la licence grâce à un couple de clé RSA. Nous devons donc dans un premier temps générer une paire de clé RSA si aucune existe actuellement : 

 async generateKeyPairRSA(): Promise<void> {
const { privateKey, publicKey } = await generateKeyPairSync('rsa', {
modulusLength: 512,
privateKeyEncoding: { type: 'pkcs1', format: 'pem' },
publicKeyEncoding: { type: 'pkcs1', format: 'pem' },
})
await writeFileSync('./rsa_licence', privateKey)
await writeFileSync('./rsa_licence.pub', publicKey)
}

Vous aurez également besoin de deux méthodes afin de travailler avec ces clés : 

  • Une méthode permettant de récupérer la clé privé RSA : cette méthode sera uniquement disponible pour votre backend, elle ne doit en aucun cas être exposée.
async getPrivateKey(): Promise<string> {
let private_key
let exist = await existsSync("./rsa_licence")
if(!exist) {
await this.generateKeyPairRSA()
}
private_key = await readFileSync("./rsa_licence", {encoding: 'utf-8'})
return private_key
}
  • La seconde méthode permet de récupérer la clé publique RSA, permettant de déchiffrer la licence et ainsi récupérer ses informations : Cette méthode peut être exposé sur un endpoint API afin que votre client puisse récupérer cette clé publique.
async getPublicKey(): Promise<string> {
let public_key
let exist = await existsSync("./rsa_licence.pub")
if(!exist) {
await this.generateKeyPairRSA()
}
public_key = await readFileSync("./rsa_licence.pub", {encoding: 'utf-8'})
return public_key
}

Chiffrer votre licence applicative avec NestJS et Crypto

Une fois notre paire de clé RSA générée, il ne vous reste plus qu'à générer une licence à partir d'un objet json contenant les informations de votre licence (ID du client associé à la licence, quota d'appareils, date de validité etc.)

async generateLicenceKey(licence_info: any, private_key: string): Promise<string> {
const signer = createSign('rsa-sha256')
signer.update(licence_info)
const encoded = Buffer.from(licence_info).toString('hex')
const signature = signer.sign(private_key, 'hex')
const licenseKey = `${encoded}.${signature}`

return licenseKey
}

Une fois votre licence générée, vous pouvez l'enregistrer en BDD, associé à l'utilisateur auquel elle appartient.

Déchiffrer votre licence applicative

Côté client, si vous souhaitez déchiffrer votre licence afin de vérifier les informations de celle-ci (licence encore valide ? Bon utilisateur associé à cette licence ? etc.), voici la méthode : 

async decryptLicence(licence: string, public_key: string): Promise<any> {
const [encoded, signature] = licence.split('.')
const data = Buffer.from(encoded, 'hex').toString()

// Create an RSA verifier
const verifier = createVerify('rsa-sha256')
verifier.update(data)

// Verify the signature for the data using the public key
const valid = verifier.verify(public_key, signature, 'hex')

return {valid, data}
}

Conclusion

Ce petit service vous permet donc de générer des licences sécurisées et simples par le biais des clé RSA. A vous d'améliorer ce service afin de le rendre plus sécurisé si nécessaire et/ou de le complexifié.

Un projet, une idée ? Contactez-moi !

Logo Galibert Thomas Développement

Développeur full-stack et DevOps freelance sur Toulouse avec cinq ans d'expérience. J'ai travaillé sur divers projets en tant que consultant indépendant, apportant mes compétences en développement logiciel et en gestion des opérations pour aider mes clients à atteindre leurs objectifs.

Vous avez un projet et vous souhaitez vous faire accompagner ? Que ce soit un site web vitrine, une boutique e-commerce, une application web, mobile ou desktop, n'hésitez pas a me contacter. Je trouverez la meilleure solution à votre besoin.

© Thomas GALIBERT - Développeur Fullstack & DevOps - Toulouse - 2023