# Dokumente schützen und entsperren

Wie die Sicherheitsaktionen zusammenspielen und in welcher Reihenfolge Sie sie aufrufen, wenn Sie ein Dokument schützen oder entsperren.

Die Sicherheit eines PDFs besteht aus zwei getrennten Dingen, und die richtige
Reihenfolge hängt davon ab, die beiden auseinanderzuhalten. Ein **Passwort**
verschlüsselt die Datei und steuert, wer sie *öffnen* darf.
**Einschränkungen** sind Berechtigungs-Flags, die steuern, was ein Leser *tun*
darf, sobald das Dokument offen ist: drucken, kopieren, bearbeiten. Dieser
Leitfaden ordnet die fünf Sicherheitsaktionen zu einem Ablauf zum Schützen vor
der Verteilung und einem Ablauf zum Entsperren.

## Die Sicherheitsaktionen

| Aktion | Route | Was sie tut |
| --- | --- | --- |
| [Passwort hinzufügen](/docs/api/add-password-to-pdf) | `add_password` | Verschlüsselt das PDF und legt das Passwort fest, das zum Öffnen nötig ist. |
| [Einschränkungen hinzufügen](/docs/api/add-restrictions-to-pdf) | `add_restrictions` | Setzt Berechtigungs-Flags (Drucken, Kopieren, Bearbeiten) hinter einem Besitzerpasswort; kann zusätzlich ein Passwort zum Öffnen setzen. |
| [Passwort entfernen](/docs/api/remove-password-from-pdf) | `remove_password` | Entschlüsselt ein PDF, wenn Sie sein aktuelles Passwort angeben. |
| [Einschränkungen entfernen](/docs/api/remove-restrictions-from-pdf) | `remove_restrictions` | Setzt alle Berechtigungs-Flags zurück. |
| [Signaturen entfernen](/docs/api/remove-signatures-from-pdf) | `remove_signatures` | Entfernt kryptografische Signaturen und Zeitstempel. |

<Info>
  **Passwörter und Einschränkungen.** `add_password` nimmt ein einziges
  `password` entgegen: das Passwort, das ein Leser zum Öffnen der Datei
  eingibt. `add_restrictions` nimmt ein `owner_password` entgegen, das die
  Berechtigungs-Flags schützt, sowie ein optionales `user_password`, das als
  Passwort zum Öffnen dient. Setzen Sie `user_password`, verlangt das Dokument
  ein Passwort zum Öffnen; lassen Sie es weg, kann jeder es öffnen, bleibt aber
  an die Berechtigungs-Flags gebunden.
</Info>

## Die eine Regel, die die Reihenfolge bestimmt

<Warning>
  **Verschlüsseln Sie zuletzt.** Ein verschlüsseltes PDF lässt sich von keiner
  anderen Aktion öffnen, weil es kein Feld gibt, über das sich sein Passwort
  angeben ließe. Führen Sie deshalb zuerst alle Schritte für Inhalt und
  Berechtigungen aus (Zusammenführen, Wasserzeichen, Einschränkungen) und fügen
  Sie das Passwort zum Öffnen als letzten Schritt hinzu. Um ein bereits
  passwortgeschütztes Dokument zu ändern, [entfernen Sie zuerst das
  Passwort](/docs/api/remove-password-from-pdf), verarbeiten Sie es und
  schützen Sie es danach erneut.
</Warning>

Wegen dieser Regel sollten Sie nicht `add_password` und danach
`add_restrictions` stapeln: Der Aufruf für die Einschränkungen kann die gerade
verschlüsselte Datei nicht öffnen. Wenn Sie **beides** brauchen, ein Passwort
zum Öffnen und Berechtigungs-Flags, setzen Sie sie in einem einzigen Aufruf von
`add_restrictions` gemeinsam über `owner_password` und `user_password`.

## Ein Dokument für die Verteilung schützen

Sichern Sie einen Bericht so ab, dass er zum Öffnen ein Passwort verlangt und
weder gedruckt noch kopiert noch bearbeitet werden kann, alles in einem
einzigen Aufruf.

<Steps>

<Step title="Zuerst den Inhalt vorbereiten">
  Erledigen Sie jetzt alles, was Zusammenführen, Wasserzeichen oder Seiten
  betrifft, solange das Dokument noch unverschlüsselt ist. Siehe [Aktionen
  verketten](/docs/api/chaining-actions).
</Step>

<Step title="Einschränkungen und ein Passwort zum Öffnen anwenden">
  `POST /v1/add_restrictions` mit einem `owner_password` (schützt die
  Berechtigungen), einem `user_password` (dem Passwort zum Öffnen) und den
  Berechtigungs-Flags auf `false` für alles, was Sie verbieten wollen.
</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>

Wenn Sie nur ein Passwort zum Öffnen und keine Berechtigungs-Flags brauchen,
ist `add_password` der einfachere Aufruf:

```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
```

Sowohl `add_password` als auch `add_restrictions` nehmen ein
`encryption_algorithm` von `AES-128` (die Voreinstellung) oder `AES-256`
entgegen. Alle Felder finden Sie unter [Passwort
hinzufügen](/docs/api/add-password-to-pdf) und [Einschränkungen
hinzufügen](/docs/api/add-restrictions-to-pdf).

## Ein Dokument entsperren

Wenn Sie die Zugangsdaten zu einem geschützten Dokument besitzen, entschlüsseln
Sie zuerst und setzen Sie dann die Berechtigungs-Flags zurück.

<Steps>

<Step title="Das Passwort zum Öffnen entfernen">
  `POST /v1/remove_password` mit dem aktuellen `password` des Dokuments. Das
  Ergebnis verlangt zum Öffnen kein Passwort mehr, sodass spätere Schritte es
  lesen können.
</Step>

<Step title="Die Einschränkungen zurücksetzen">
  `POST /v1/remove_restrictions` entfernt die Berechtigungs-Flags und
  hinterlässt ein PDF ohne Einschränkungen.
</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` hat kein Passwortfeld und funktioniert deshalb bei
  einem Dokument, das eingeschränkt, aber nicht passwortgeschützt ist. Hat ein
  Dokument ein Passwort zum Öffnen, führen Sie zuerst `remove_password` aus,
  wie es der Ablauf oben tut, damit der Aufruf für die Einschränkungen es lesen
  kann.
</Info>

## Signaturen entfernen

Eine kryptografische Signatur versiegelt ein PDF: Jede Bearbeitung macht sie
ungültig. Wenn Sie ein signiertes Dokument erneut verarbeiten müssen, entfernen
Sie zuerst mit `remove_signatures` die Signaturen und Zeitstempel. Das macht
die Signaturen tatsächlich ungültig, was sich nicht vermeiden lässt, sobald
sich der Inhalt ändert.

```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
```

## Siehe auch

<CardGroup cols={2}>

<Card title="Passwort hinzufügen" href="/docs/api/add-password-to-pdf">
  Ein PDF mit einem Passwort zum Öffnen verschlüsseln.
</Card>

<Card title="Einschränkungen hinzufügen" href="/docs/api/add-restrictions-to-pdf">
  Die vollständige Matrix der Berechtigungs-Flags festlegen.
</Card>

<Card title="Passwort entfernen" href="/docs/api/remove-password-from-pdf">
  Ein PDF entschlüsseln, dessen Passwort Sie haben.
</Card>

<Card title="Aktionen verketten" href="/docs/api/chaining-actions">
  Ein Wasserzeichen aufbringen oder zusammenführen, bevor Sie verschlüsseln.
</Card>

</CardGroup>
