# Protéger et déverrouiller des documents

Comment les actions de sécurité s’articulent entre elles, et dans quel ordre les appeler pour protéger ou déverrouiller un document.

La sécurité d’un PDF, ce sont deux choses distinctes, et trouver le bon ordre
suppose de savoir laquelle est laquelle. Un **mot de passe** chiffre le fichier
et contrôle qui peut l’*ouvrir*. Les **restrictions** sont des indicateurs
d’autorisation qui contrôlent ce qu’un lecteur peut *faire* une fois le
document ouvert : imprimer, copier, modifier. Ce guide ordonne les cinq actions
de sécurité en une procédure de protection avant diffusion et une procédure de
déverrouillage.

## Les actions de sécurité

| Action | Route | Ce qu’elle fait |
| --- | --- | --- |
| [Ajouter un mot de passe](/docs/api/add-password-to-pdf) | `add_password` | Chiffre le PDF et définit le mot de passe nécessaire pour l’ouvrir. |
| [Ajouter des restrictions](/docs/api/add-restrictions-to-pdf) | `add_restrictions` | Définit les indicateurs d’autorisation (impression, copie, modification) derrière un mot de passe propriétaire ; peut aussi définir un mot de passe d’ouverture. |
| [Supprimer le mot de passe](/docs/api/remove-password-from-pdf) | `remove_password` | Déchiffre un PDF lorsque vous fournissez son mot de passe actuel. |
| [Supprimer les restrictions](/docs/api/remove-restrictions-from-pdf) | `remove_restrictions` | Efface tous les indicateurs d’autorisation. |
| [Supprimer les signatures](/docs/api/remove-signatures-from-pdf) | `remove_signatures` | Supprime les signatures cryptographiques et les horodatages. |

<Info>
  **Mots de passe et restrictions.** `add_password` prend un seul `password` :
  le mot de passe qu’un lecteur saisit pour ouvrir le fichier.
  `add_restrictions` prend un `owner_password` qui protège les indicateurs
  d’autorisation, plus un `user_password` facultatif qui fait office de mot de
  passe d’ouverture. Définissez `user_password` et le document exigera un mot
  de passe pour s’ouvrir ; omettez-le et n’importe qui pourra l’ouvrir, tout en
  restant soumis aux indicateurs d’autorisation.
</Info>

## La règle unique qui gouverne l’ordre

<Warning>
  **Chiffrez en dernier.** Aucune autre action ne peut ouvrir un PDF chiffré,
  car il n’existe aucun champ pour fournir son mot de passe. Exécutez donc
  d’abord toutes les étapes de contenu et d’autorisation (fusion, filigrane,
  restrictions) et ajoutez le mot de passe d’ouverture en étape finale. Pour
  modifier un document déjà protégé par mot de passe, [supprimez le mot de
  passe](/docs/api/remove-password-from-pdf) d’abord, traitez-le, puis
  protégez-le à nouveau.
</Warning>

En raison de cette règle, n’empilez pas `add_password` puis
`add_restrictions` : l’appel de restrictions ne peut pas ouvrir le fichier qui
vient d’être chiffré. Lorsque vous avez besoin **à la fois** d’un mot de passe
d’ouverture et d’indicateurs d’autorisation, définissez-les dans un seul appel
à `add_restrictions` en utilisant `owner_password` et `user_password` ensemble.

## Protéger un document en vue de sa diffusion

Verrouillez un rapport pour qu’il exige un mot de passe à l’ouverture et ne
puisse être ni imprimé, ni copié, ni modifié, le tout en un seul appel.

<Steps>

<Step title="Préparez d’abord le contenu">
  Effectuez dès maintenant les fusions, les filigranes ou le travail sur les
  pages, pendant que le document n’est pas encore chiffré. Consultez
  [Enchaîner les actions](/docs/api/chaining-actions).
</Step>

<Step title="Appliquez des restrictions et un mot de passe d’ouverture">
  `POST /v1/add_restrictions` avec un `owner_password` (qui protège les
  autorisations), un `user_password` (le mot de passe d’ouverture) et les
  indicateurs d’autorisation à `false` pour ce que vous voulez interdire.
</Step>

</Steps>

<CodeGroup>

```bash title="cURL"
curl https://api.pdfblocks.com/v1/add_restrictions \
  -H 'X-API-Key: your_api_key' \
  -F file=@input.pdf \
  -F owner_password='owner-secret' \
  -F user_password='open-secret' \
  -F allow_print=false \
  -F allow_copy_content=false \
  -F allow_change_content=false \
  -o protected.pdf
```

```python title="Python"
# pip install requests
import requests

with open('input.pdf', 'rb') as file:
    response = requests.post(
        'https://api.pdfblocks.com/v1/add_restrictions',
        headers={'X-API-Key': 'your_api_key'},
        files={'file': file},
        data={
            'owner_password': 'owner-secret',
            'user_password': 'open-secret',
            'allow_print': 'false',
            'allow_copy_content': 'false',
            'allow_change_content': 'false',
        },
    )

response.raise_for_status()
with open('protected.pdf', 'wb') as output:
    output.write(response.content)
```

```javascript title="Node.js"
// Node.js 18+
import { readFile, writeFile } from 'node:fs/promises';

const body = new FormData();
body.set('file', new Blob([await readFile('input.pdf')]), 'input.pdf');
body.set('owner_password', 'owner-secret');
body.set('user_password', 'open-secret');
body.set('allow_print', 'false');
body.set('allow_copy_content', 'false');
body.set('allow_change_content', 'false');

const response = await fetch('https://api.pdfblocks.com/v1/add_restrictions', {
  method: 'POST',
  headers: { 'X-API-Key': 'your_api_key' },
  body,
});

if (!response.ok) throw new Error(`Request failed: ${response.status}`);
await writeFile('protected.pdf', Buffer.from(await response.arrayBuffer()));
```

```php title="PHP"
<?php
$ch = curl_init('https://api.pdfblocks.com/v1/add_restrictions');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['X-API-Key: your_api_key'],
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => [
        'file' => new CURLFile('input.pdf', 'application/pdf'),
        'owner_password' => 'owner-secret',
        'user_password' => 'open-secret',
        'allow_print' => 'false',
        'allow_copy_content' => 'false',
        'allow_change_content' => 'false',
    ],
]);

$pdf = curl_exec($ch);
if (curl_getinfo($ch, CURLINFO_HTTP_CODE) === 200) {
    file_put_contents('protected.pdf', $pdf);
}
```

```ruby title="Ruby"
# gem install http
require 'http'

response = HTTP
  .headers('X-API-Key' => 'your_api_key')
  .post('https://api.pdfblocks.com/v1/add_restrictions', form: {
    file: HTTP::FormData::File.new('input.pdf'),
    owner_password: 'owner-secret',
    user_password: 'open-secret',
    allow_print: 'false',
    allow_copy_content: 'false',
    allow_change_content: 'false',
  })

File.write('protected.pdf', response.body) if response.status.success?
```

```go title="Go"
package main

import (
	"bytes"
	"io"
	"mime/multipart"
	"net/http"
	"os"
)

func main() {
	var buf bytes.Buffer
	form := multipart.NewWriter(&buf)

	file, _ := os.Open("input.pdf")
	defer file.Close()
	part, _ := form.CreateFormFile("file", "input.pdf")
	io.Copy(part, file)

	form.WriteField("owner_password", "owner-secret")
	form.WriteField("user_password", "open-secret")
	form.WriteField("allow_print", "false")
	form.WriteField("allow_copy_content", "false")
	form.WriteField("allow_change_content", "false")
	form.Close()

	req, _ := http.NewRequest("POST",
		"https://api.pdfblocks.com/v1/add_restrictions", &buf)
	req.Header.Set("Content-Type", form.FormDataContentType())
	req.Header.Set("X-API-Key", "your_api_key")

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()

	out, _ := os.Create("protected.pdf")
	defer out.Close()
	io.Copy(out, res.Body)
}
```

```csharp title="C#"
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "your_api_key");

using var form = new MultipartFormDataContent
{
    { new ByteArrayContent(File.ReadAllBytes("input.pdf")), "file", "input.pdf" },
    { new StringContent("owner-secret"), "owner_password" },
    { new StringContent("open-secret"), "user_password" },
    { new StringContent("false"), "allow_print" },
    { new StringContent("false"), "allow_copy_content" },
    { new StringContent("false"), "allow_change_content" },
};

var response = await client.PostAsync(
    "https://api.pdfblocks.com/v1/add_restrictions", form);
response.EnsureSuccessStatusCode();
await File.WriteAllBytesAsync(
    "protected.pdf", await response.Content.ReadAsByteArrayAsync());
```

</CodeGroup>

Si vous n’avez besoin que d’un mot de passe d’ouverture et d’aucun indicateur
d’autorisation, `add_password` est l’appel le plus simple :

```bash title="cURL"
curl https://api.pdfblocks.com/v1/add_password \
  -H 'X-API-Key: your_api_key' \
  -F file=@input.pdf \
  -F password='pa$$word' \
  -o encrypted.pdf
```

`add_password` comme `add_restrictions` acceptent un `encryption_algorithm`
valant `AES-128` (la valeur par défaut) ou `AES-256`. Consultez [Ajouter un mot
de passe à un PDF](/docs/api/add-password-to-pdf) et [Ajouter des restrictions
à un PDF](/docs/api/add-restrictions-to-pdf) pour tous les champs.

## Déverrouiller un document

Pour lever une protection dont vous détenez les identifiants, déchiffrez
d’abord, puis effacez les indicateurs d’autorisation.

<Steps>

<Step title="Supprimez le mot de passe d’ouverture">
  `POST /v1/remove_password` avec le `password` actuel du document. Le résultat
  n’exige plus de mot de passe à l’ouverture, si bien que les étapes suivantes
  peuvent le lire.
</Step>

<Step title="Effacez les restrictions">
  `POST /v1/remove_restrictions` supprime les indicateurs d’autorisation et
  laisse un PDF sans restrictions.
</Step>

</Steps>

<CodeGroup>

```bash title="cURL"
# 1. Decrypt with the known password.
curl -sS https://api.pdfblocks.com/v1/remove_password \
  -H 'X-API-Key: your_api_key' \
  -F file=@protected.pdf \
  -F password='open-secret' |
# 2. Clear the permission flags from the decrypted bytes.
curl -sS https://api.pdfblocks.com/v1/remove_restrictions \
  -H 'X-API-Key: your_api_key' \
  -F 'file=@-;filename=unlocked.pdf;type=application/pdf' \
  -o unrestricted.pdf
```

```python title="Python"
# pip install requests
import requests

BASE = 'https://api.pdfblocks.com'
HEADERS = {'X-API-Key': 'your_api_key'}

# 1. Decrypt with the known password.
with open('protected.pdf', 'rb') as file:
    unlocked = requests.post(
        f'{BASE}/v1/remove_password',
        headers=HEADERS,
        files={'file': file},
        data={'password': 'open-secret'},
    )
unlocked.raise_for_status()

# 2. Clear the permission flags from the decrypted bytes.
unrestricted = requests.post(
    f'{BASE}/v1/remove_restrictions',
    headers=HEADERS,
    files={'file': ('unlocked.pdf', unlocked.content, 'application/pdf')},
)
unrestricted.raise_for_status()

with open('unrestricted.pdf', 'wb') as output:
    output.write(unrestricted.content)
```

</CodeGroup>

<Info>
  `remove_restrictions` n’a pas de champ de mot de passe : il fonctionne donc
  sur un document soumis à des restrictions mais non protégé par mot de passe.
  Si un document a un mot de passe d’ouverture, exécutez d’abord
  `remove_password`, comme le fait la procédure ci-dessus, pour que l’appel de
  restrictions puisse le lire.
</Info>

## Supprimer les signatures

Une signature cryptographique verrouille un PDF : toute modification l’invalide.
Si vous devez retraiter un document signé, supprimez d’abord les signatures et
les horodatages avec `remove_signatures`. Cela invalide bien les signatures, ce
qui est inévitable dès lors que le contenu change.

```bash title="cURL"
curl https://api.pdfblocks.com/v1/remove_signatures \
  -H 'X-API-Key: your_api_key' \
  -F file=@signed.pdf \
  -o unsigned.pdf
```

## Voir aussi

<CardGroup cols={2}>

<Card title="Ajouter un mot de passe" href="/docs/api/add-password-to-pdf">
  Chiffrez un PDF avec un mot de passe d’ouverture.
</Card>

<Card title="Ajouter des restrictions" href="/docs/api/add-restrictions-to-pdf">
  Définissez toute la matrice des indicateurs d’autorisation.
</Card>

<Card title="Supprimer un mot de passe" href="/docs/api/remove-password-from-pdf">
  Déchiffrez un PDF dont vous avez le mot de passe.
</Card>

<Card title="Enchaîner les actions" href="/docs/api/chaining-actions">
  Apposez un filigrane ou fusionnez avant de chiffrer.
</Card>

</CardGroup>
