Wat is IPFS en waarom zou het je moeten interesseren?

IPFS is alsof BitTorrent een kind heeft gekregen met het web. Het is een peer-to-peer hypermedia protocol dat is ontworpen om het web sneller, veiliger en opener te maken. In plaats van gecentraliseerde servers gebruikt IPFS een netwerk van gedistribueerde nodes om bestanden op te slaan en te delen. Dit betekent:

  • Geen enkel storingspunt
  • Verbeterde gegevensintegriteit en beschikbaarheid
  • Weerstand tegen censuur en DDoS-aanvallen
  • Mogelijke kostenbesparingen op bandbreedte en opslag

Klinkt als een droom voor ontwikkelaars, toch? Laten we het werkelijkheid maken.

Je IPFS-aangedreven backend instellen

Laten we eerst aan de slag gaan met wat code. We gebruiken Node.js en de `ipfs-http-client` bibliotheek om met IPFS te werken.

1. Installatie en Setup

Begin met het installeren van de benodigde pakketten:

npm install ipfs-http-client express multer

Nu maken we onze basis Express-server met IPFS-integratie:


const express = require('express');
const multer = require('multer');
const { create } = require('ipfs-http-client');

const app = express();
const upload = multer({ storage: multer.memoryStorage() });

// Verbinden met het IPFS-netwerk
const ipfs = create({ host: 'localhost', port: '5001', protocol: 'http' });

app.post('/upload', upload.single('file'), async (req, res) => {
  try {
    const file = req.file;
    const result = await ipfs.add(file.buffer);
    res.json({ cid: result.cid.toString() });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.listen(3000, () => console.log('Server draait op poort 3000'));

Dit stelt een basisserver in die bestandsuploads kan accepteren en deze op IPFS kan opslaan.

2. Veilige Bestandsdeling

Laten we nu wat beveiliging toevoegen aan ons bestandsdelingssysteem. We implementeren inhoudscodering voordat we naar IPFS uploaden:


const crypto = require('crypto');

function encryptBuffer(buffer, key) {
  const iv = crypto.randomBytes(16);
  const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
  return Buffer.concat([iv, cipher.update(buffer), cipher.final()]);
}

app.post('/upload', upload.single('file'), async (req, res) => {
  try {
    const file = req.file;
    const encryptionKey = crypto.randomBytes(32);
    const encryptedBuffer = encryptBuffer(file.buffer, encryptionKey);
    
    const result = await ipfs.add(encryptedBuffer);
    res.json({ 
      cid: result.cid.toString(),
      key: encryptionKey.toString('hex')
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

Nu zijn onze bestanden versleuteld voordat ze IPFS bereiken, wat een extra beveiligingslaag toevoegt.

Bestanden Ophalen: De IPFS Manier

Uiteraard is het uploaden van bestanden slechts de helft van het werk. Laten we een route toevoegen om bestanden op te halen en te decoderen:


function decryptBuffer(encryptedBuffer, key) {
  const iv = encryptedBuffer.slice(0, 16);
  const encryptedContent = encryptedBuffer.slice(16);
  const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
  return Buffer.concat([decipher.update(encryptedContent), decipher.final()]);
}

app.get('/file/:cid', async (req, res) => {
  try {
    const { cid } = req.params;
    const { key } = req.query;

    if (!key) {
      return res.status(400).json({ error: 'Decryptiesleutel is vereist' });
    }

    const encryptedContent = await ipfs.cat(cid);
    const decryptionKey = Buffer.from(key, 'hex');
    const decryptedContent = decryptBuffer(encryptedContent, decryptionKey);

    res.send(decryptedContent);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

De Plot Dikt In: Geavanceerde Functies

Nu we de basis onder de knie hebben, laten we het wat spannender maken met enkele geavanceerde functies:

1. Inhoudsadressering en Deduplicatie

IPFS gebruikt inhoudsadressering, wat betekent dat identieke bestanden slechts één keer worden opgeslagen. Dit is geweldig voor deduplicatie, maar kan een privacyprobleem zijn. Om dit te verzachten, kunnen we een willekeurig zout aan elk bestand toevoegen voordat we het versleutelen:


function addSaltAndEncrypt(buffer, key) {
  const salt = crypto.randomBytes(16);
  const saltedBuffer = Buffer.concat([salt, buffer]);
  return encryptBuffer(saltedBuffer, key);
}

2. Automatische Bestandsverval

We kunnen automatische bestandsverval implementeren met behulp van het pin-systeem van IPFS. Wanneer een bestand wordt geüpload, pinnen we het en stellen we een timer in om het na een bepaalde periode te unpinnen:


async function pinWithExpiration(cid, expirationTime) {
  await ipfs.pin.add(cid);
  setTimeout(async () => {
    await ipfs.pin.rm(cid);
    console.log(`Bestand unpinned: ${cid}`);
  }, expirationTime);
}

app.post('/upload', upload.single('file'), async (req, res) => {
  // ... vorige uploadcode ...
  await pinWithExpiration(result.cid, 24 * 60 * 60 * 1000); // 24 uur
  // ... rest van de code ...
});

3. Toegangscontrole

Voor meer gedetailleerde toegangscontrole kunnen we een eenvoudig token-gebaseerd systeem implementeren:


const accessTokens = new Map();

function generateAccessToken(cid) {
  const token = crypto.randomBytes(16).toString('hex');
  accessTokens.set(token, cid);
  return token;
}

app.post('/upload', upload.single('file'), async (req, res) => {
  // ... vorige uploadcode ...
  const accessToken = generateAccessToken(result.cid);
  res.json({ 
    accessToken,
    key: encryptionKey.toString('hex')
  });
});

app.get('/file/:token', async (req, res) => {
  const { token } = req.params;
  const cid = accessTokens.get(token);
  if (!cid) {
    return res.status(403).json({ error: 'Ongeldig toegangstoken' });
  }
  // ... rest van de bestandsophaalcode ...
});

De Olifant in de Kamer: Potentiële Valkuilen

Voordat je de volgende Dropbox op IPFS bouwt, laten we het hebben over enkele mogelijke problemen:

  • Prestaties: IPFS kan trager zijn dan traditionele gecentraliseerde opslag voor vaak opgevraagde bestanden.
  • Gegevenspersistentie: Bestanden op IPFS zijn alleen beschikbaar zolang ten minste één node ze host.
  • Juridische Zorgen: De gedecentraliseerde aard van IPFS kan het moeilijk maken om aan bepaalde regelgeving te voldoen (GDPR, iemand?).
  • Sleutelbeheer: Het verliezen van de versleutelingssleutel betekent dat je voor altijd de toegang tot het bestand verliest. Implementeer een robuust sleutelbeheersysteem!

Afronding: IPFS of Niet IPFS?

IPFS biedt een revolutionaire benadering van bestandsopslag en -deling, maar het is geen wondermiddel. Het blinkt uit in scenario's waar decentralisatie, censuurbestendigheid en wereldwijde distributie belangrijke vereisten zijn.

Voor je volgende project, overweeg deze vragen:

  • Heb je echte decentralisatie nodig, of is een gedistribueerde CDN voldoende?
  • Hoe gevoelig zijn je gegevens, en kun je omgaan met de complexiteit van versleuteling?
  • Ben je klaar om de unieke uitdagingen van een peer-to-peer systeem aan te gaan?

Als je op deze vragen ja hebt geantwoord, gefeliciteerd! Je bent klaar om deel te nemen aan de gedecentraliseerde opslagrevolutie. Moge de (gedecentraliseerde) kracht met je zijn!

"De toekomst is al hier – hij is alleen niet gelijkmatig verdeeld." - William Gibson

Ga nu en decentraliseer alles! 🚀