> ## Content Index
> Fetch the complete content index at: https://arabroot.io/llms.txt
> Use this file to discover other available public pages before exploring further.

# استخدام GPG عملياً: من إنشاء المفتاح إلى توقيع Git
- URL: https://arabroot.io/articles/استخدام-gpg-عمليا-من-انشاء-المفتاح-الى-توقيع-git/
- Published: 2026-10-10T13:15:00.000Z
- Updated: 2026-10-09T14:03:06.000Z
- Description: كيف تنشئ مفتاح GPG وتتحقق من بصمة غيرك، ثم تشفر ملفاتك وتوقعها وتوقع بها Git Commits.
- Author: فريق عرب رووت
- Tags: الأدلة التقنية, الأمن السيبراني, الاستضافة الذاتية

في [شرح GPG وOpenPGP](https://arabroot.io/articles/%D8%B4%D8%B1%D8%AD-gpg-%D9%88-openpgp-%D8%A7%D9%84%D8%AA%D8%B4%D9%81%D9%8A%D8%B1-%D9%88%D8%A7%D9%84%D8%AA%D9%88%D9%82%D9%8A%D8%B9-%D8%A8%D8%A7%D9%84%D9%85%D9%81%D8%AA%D8%A7%D8%AD-%D8%A7%D9%84%D8%B9%D8%A7%D9%85/) تحدثنا عن الفكرة: المفتاح العام والخاص، والتشفير الهجين، والبصمة، وكيف تعرف أن المفتاح لصاحبه، ولماذا تحتاج تاريخ انتهاء وشهادة إلغاء. وفي هذا المقال سوف ننفذ كل ذلك بالأوامر، بحيث تخرج منه وأنت تملك مفتاحاً حديثاً بإعداد صحيح، وتعرف كيف تتبادله مع غيرك وتتحقق من مفاتيحهم، وتشفر وتوقع، وتوقع Git Commits، وتتحقق من ملف نزلته من الإنترنت، وتعرف ماذا تفعل عندما يظهر لك خطأ من أخطاء GPG المشهورة. وسوف نتناول في هذا المقال ما يلي:

- تثبيت GPG على Linux وmacOS وWindows.
- إنشاء مفتاح ed25519 بمفتاح تشفير فرعي cv25519 وتاريخ انتهاء، وشهادة الإلغاء.
- تصدير المفتاح العام ونشره على keys.openpgp.org وعلى نطاقك عبر WKD.
- استيراد مفتاح شخص آخر والتحقق من بصمته، ثم التشفير وفك التشفير والتوقيع والتحقق.
- تشفير البريد في Thunderbird، وتوقيع Git Commits والوسوم Tags.
- التحقق من ملف منزل بمثال حقيقي من Debian.
- النسخ الاحتياطي ونقل المفتاح إلى جهاز جديد، وتمديد تاريخ الانتهاء، والإلغاء، ومفاتيح الأمان مثل YubiKey.
- الأخطاء الشائعة وحلولها، وجدول بالأوامر.

## التجربة: Alice وBob في Container واحد

حتى تكون كل المخرجات في هذا المقال حقيقية دون أن نلمس مفاتيح أي شخص حقيقي، شغلنا التجربة كلها في Container مؤقت من Debian 13.7 فيه GnuPG، ولكل شخصية وهمية مجلد GPG خاص بها يحدده المتغير `GNUPGHOME`، كأن كل مجلد جهاز مستقل، والملفات تنتقل بينهم عبر مجلد مشترك يقوم مقام البريد. والصورة التالية تبين ترتيب التجربة:

![Container واحد اسمه lab-gpg-box فيه مجلد GPG لكل من Alice وBob وCarol ولجهاز Alice الجديد، ومجلد مشترك في الوسط تمر عبره المفاتيح العامة والرسائل المشفرة والتوقيعات وشهادة الإلغاء والنسخة الاحتياطية](https://arabroot.io/content/images/2026/10/gpg-practice-01-lab.webp)

أربعة مجلدات GNUPGHOME في Container واحد، ومجلد مشترك يقوم مقام البريد بينهم

والملف `Dockerfile` الذي بنينا منه ال Image هو التالي:

```dockerfile
FROM debian:13.7-slim
RUN apt-get update && apt-get install -y --no-install-recommends gnupg git curl ca-certificates dirmngr gpg-wks-client pinentry-curses && rm -rf /var/lib/apt/lists/*
```

ثم بنيناه وشغلناه، وكل أمر في بقية المقال نفذناه داخله عبر `docker exec` مع المتغير `GNUPGHOME` للشخصية المطلوبة:

```bash
docker build -t lab-gpg-debian:13.7 .
docker run -d --rm --name lab-gpg-box -w /lab lab-gpg-debian:13.7 sleep infinity
docker exec lab-gpg-box sh -c 'mkdir -p -m 700 /lab/alice /lab/bob /lab/carol /lab/alice-laptop; mkdir -p /lab/shared'
docker exec -it -e GNUPGHOME=/lab/alice lab-gpg-box bash
```

ولاحظ نقطة مهمة قبل أن نبدأ: كل أمر يستخدم المفتاح الخاص يطلب كلمة المرور Passphrase عبر برنامج صغير اسمه pinentry، يظهر لك نافذة أو مربعاً في الطرفية. ولأننا شغلنا الأوامر آلياً أضفنا لهذه الأوامر الخيارات `--batch --pinentry-mode loopback --passphrase "..."` حتى تمرر كلمة المرور مباشرة، وتركناها في الأوامر كما نفذناها. أما على جهازك فلا تضعها أبداً، لأن كلمة المرور سوف تحفظ في سجل الأوامر Shell History، فاحذفها واترك pinentry يسألك.

## تثبيت GPG على Linux وmacOS وWindows

- **Linux:** GnuPG موجود في كل التوزيعات، وفي Debian وUbuntu تثبته بالأمر `sudo apt install gnupg`، وفي Fedora وRHEL بالأمر `sudo dnf install gnupg2`. والإصدار الذي يأتي مع التوزيعة المستقرة غالباً أقدم من الإصدار الحالي، ففي Debian 13 الإصدار 2.4.7، بينما الإصدار المستقر الحالي من المشروع 2.5.24 بحسب [صفحة التنزيل](https://gnupg.org/download/index.html?ref=arabroot.io)، وكل ما في هذا المقال يعمل على الاثنين.
- **macOS:** أمامك طريقتان: الأولى `brew install gnupg` من Homebrew، و[بحسب صفحة الحزمة](https://formulae.brew.sh/formula/gnupg?ref=arabroot.io) فالإصدار فيه 2.5.24 برخصة GPL-3.0-or-later، والثانية [GPG Suite](https://gpgtools.org/?ref=arabroot.io) الذي يضيف واجهة رسومية لإدارة المفاتيح هي GPG Keychain، وهي مجانية، أما إضافة البريد GPG Mail لبرنامج Mail من Apple فتحتاج اشتراكاً مدفوعاً Support Plan.
- **Windows:** [Gpg4win](https://www.gpg4win.org/?ref=arabroot.io)، وآخر إصدار منه 5.1.1 بتاريخ 23 سبتمبر 2026، وهو برنامج حر مجاني و[أغلب مكوناته برخصة GNU GPL](https://www.gpg4win.org/license.html?ref=arabroot.io)، ويأتي مع Kleopatra لإدارة المفاتيح والشهادات من واجهة رسومية، وGpgOL لبرنامج Outlook، وGpgEX لقائمة الملفات في Explorer. وبعد التثبيت يعمل الأمر `gpg` نفسه من PowerShell.

وتأكد من الإصدار بعد التثبيت، والمخرج في التجربة سوف يكون كما يلي:

```text
$ gpg --version | head -3
gpg (GnuPG) 2.4.7
libgcrypt 1.11.0
Copyright (C) 2024 g10 Code GmbH
```

## إنشاء المفتاح

الطريقة التفاعلية هي الأمر `gpg --full-generate-key`، وهو يسألك عن نوع المفتاح ومدته والاسم والبريد وكلمة المرور خطوة خطوة. ولكننا نفضل الأمر `--quick-gen-key` لأنه يجعلك تحدد كل شيء صراحة في سطر واحد، فنبدأ بالمفتاح الرئيسي من نوع ed25519 بصلاحيتي التوقيع وشهادة المفاتيح، ومدته سنتان:

```bash
gpg --batch --pinentry-mode loopback --passphrase "alice-lab-pass" \
    --quick-gen-key "Alice Example <alice@example.test>" ed25519 sign,cert 2y
```

والمخرج سوف يكون كما يلي:

```text
gpg: keybox '/lab/alice/pubring.kbx' created
gpg: /lab/alice/trustdb.gpg: trustdb created
gpg: directory '/lab/alice/openpgp-revocs.d' created
gpg: revocation certificate stored as '/lab/alice/openpgp-revocs.d/F8E558CDCE839C89D465E692C285B11B1C262E80.rev'
```

ثم نضيف المفتاح الفرعي للتشفير من نوع cv25519 بالمدة نفسها، ونستخدم البصمة الكاملة للإشارة إلى المفتاح:

```bash
gpg --batch --pinentry-mode loopback --passphrase "alice-lab-pass" \
    --quick-add-key F8E558CDCE839C89D465E692C285B11B1C262E80 cv25519 encr 2y
gpg --list-secret-keys --keyid-format long --with-subkey-fingerprints
```

والمخرج سوف يكون كما يلي:

```text
/lab/alice/pubring.kbx
----------------------
sec   ed25519/C285B11B1C262E80 2026-10-09 [SC] [expires: 2028-10-08]
      F8E558CDCE839C89D465E692C285B11B1C262E80
uid                 [ultimate] Alice Example <alice@example.test>
ssb   cv25519/7220124A948A4F79 2026-10-09 [E] [expires: 2028-10-08]
      099269D99FFC137AB5C7B9077220124A948A4F79
```

في الإعداد أعلاه لاحظ التالي:

- `sec` هو المفتاح الرئيسي وصلاحياته `[SC]`، و`ssb` هو المفتاح الفرعي للتشفير `[E]`، ولكل منهما تاريخ انتهاء بعد سنتين.
- الكلمة `[ultimate]` تعني أن GPG يثق بهذا المفتاح ثقة كاملة لأنه مفتاحك أنت.
- لم نستخدم RSA، فمفاتيح ed25519 وcv25519 أصغر وأسرع، وهي الافتراضية في GnuPG الحديث، ومدعومة في كل البرامج المنتشرة اليوم.

وقد يتساءل البعض: لماذا لا نستخدم الكلمة `default` ونريح أنفسنا؟ والإجابة في مفتاح Bob، فقد أنشأناه بالأمر المختصر `--quick-gen-key "Bob Example <bob@example.test>" default default 2y`، والنتيجة كانت كما يلي:

```text
$ gpg -k --keyid-format long bob@example.test
pub   ed25519/E60C7D75F408B810 2026-10-09 [SC] [expires: 2028-10-08]
      53C672A060A5A2FE6B3A7F80E60C7D75F408B810
uid                 [ultimate] Bob Example <bob@example.test>
sub   cv25519/380BCF94EF97A3CC 2026-10-09 [E]
```

لاحظ أن الأنواع صحيحة، ولكن المفتاح الفرعي للتشفير **بلا تاريخ انتهاء**، لأن المدة في هذا الأمر طبقت على المفتاح الرئيسي فقط. وهذا ليس كارثة، لأن انتهاء المفتاح الرئيسي يوقف المفتاح كله، ولكنه سبب كاف لتحدد كل جزء بنفسك وتنظر إلى المخرج بعد كل إنشاء.

وأما كلمة المرور فهي تحمي المفتاح الخاص على القرص، فإذا سرق الملف لم يستطع السارق استخدامه دونها، فاختر كلمة طويلة، والأفضل جملة من عدة كلمات، واحفظها في مدير كلمات المرور.

## شهادة الإلغاء: جهزها اليوم

كما رأيت في المخرج السابق، أنشأ GnuPG شهادة إلغاء تلقائياً في المجلد `openpgp-revocs.d`، وهذا أول ما فيها:

```text
$ cat /lab/alice/openpgp-revocs.d/F8E558CDCE839C89D465E692C285B11B1C262E80.rev | head -20
This is a revocation certificate for the OpenPGP key:

pub   ed25519 2026-10-09 [SC] [expires: 2028-10-08]
      F8E558CDCE839C89D465E692C285B11B1C262E80
uid          Alice Example <alice@example.test>

A revocation certificate is a kind of "kill switch" to publicly
declare that a key shall not anymore be used.  It is not possible
to retract such a revocation certificate once it has been published.

Use it to revoke this key in case of a compromise or loss of
the secret key.  However, if the secret key is still accessible,
it is better to generate a new revocation certificate and give
a reason for the revocation.  For details see the description of
of the gpg command "--generate-revocation" in the GnuPG manual.

To avoid an accidental use of this file, a colon has been inserted
before the 5 dashes below.  Remove this colon with a text editor
before importing and publishing this revocation certificate.
```

وإذا أردت شهادة فيها سبب الإلغاء وتعليق يقرؤه الناس، فالأمر `--gen-revoke` يسألك عنهما، وهذه الجلسة كاملة من التجربة:

```text
$ gpg --pinentry-mode loopback --passphrase alice-lab-pass --output alice-revoke.asc --gen-revoke alice@example.test

sec  ed25519/C285B11B1C262E80 2026-10-09 Alice Example <alice@example.test>

Create a revocation certificate for this key? (y/N) y
Please select the reason for the revocation:
  0 = No reason specified
  1 = Key has been compromised
  2 = Key is superseded
  3 = Key is no longer used
  Q = Cancel
(Probably you want to select 1 here)
Your decision? 1
Enter an optional description; end it with an empty line:
> Key stored on the old laptop
>
Reason for revocation: Key has been compromised
Key stored on the old laptop
Is this okay? (y/N) y
ASCII armored output forced.
Revocation certificate created.

Please move it to a medium which you can hide away; if Mallory gets
access to this certificate he can use it to make your key unusable.
It is smart to print this certificate and store it away, just in case
your media become unreadable.  But have some caution:  The print system of
your machine might store the data and make it available to others!
```

انقل هذا الملف، والملف التلقائي أيضاً، إلى مكان بعيد عن الجهاز مثل ذاكرة USB في درج مقفل أو ورقة مطبوعة، والسبب أن من يحصل عليها يستطيع أن يلغي مفتاحك، وأن الجهاز نفسه هو ما قد تفقده.

## تصدير المفتاح العام ونشره

المفتاح العام تصدره بالأمر `--export`، والخيار `--armor` يجعله نصاً يمكن لصقه في رسالة أو صفحة:

```text
$ gpg --armor --export alice@example.test > alice.asc
$ head -3 alice.asc; wc -c alice.asc
-----BEGIN PGP PUBLIC KEY BLOCK-----

mDMEasjnfhYJKwYBBAHaRw8BAQdA0N/HWbcFA63TumW2ecVgBvP5xYEbaqcgdNna
660 alice.asc
```

ولاحظ أن المفتاح كاملاً 660 بايت فقط، وهذا من مزايا ed25519\. وبعد ذلك أمامك ثلاث طرق لنشره، وكلها شرحنا فكرتها في [قسم الثقة في مقال الشرح](https://arabroot.io/articles/%D8%B4%D8%B1%D8%AD-gpg-%D9%88-openpgp-%D8%A7%D9%84%D8%AA%D8%B4%D9%81%D9%8A%D8%B1-%D9%88%D8%A7%D9%84%D8%AA%D9%88%D9%82%D9%8A%D8%B9-%D8%A8%D8%A7%D9%84%D9%85%D9%81%D8%AA%D8%A7%D8%AD-%D8%A7%D9%84%D8%B9%D8%A7%D9%85/#trust):

1. **أرسله مباشرة** إلى من يحتاجه، مع البصمة عبر قناة أخرى.

**انشره على نطاقك عبر WKD** إذا كان لك نطاق وبريد عليه، فيجده أي برنامج من عنوان البريد وحده. والأداة `gpg-wks-client` تحسب المسار وتنشئ المجلدات، وفي Debian تجدها في `/usr/lib/gnupg/` وليست في المسار الافتراضي:

```text
$ /usr/lib/gnupg/gpg-wks-client --print-wkd-hash alice@example.test
kei1q4tipxxu1yj79k9kfukdhfy631xe alice@example.test
$ /usr/lib/gnupg/gpg-wks-client --print-wkd-url alice@example.test
https://openpgpkey.example.test/.well-known/openpgpkey/example.test/hu/kei1q4tipxxu1yj79k9kfukdhfy631xe?l=alice

$ mkdir -p openpgpkey/example.test
$ /usr/lib/gnupg/gpg-wks-client --install-key -C openpgpkey F8E558CDCE839C89D465E692C285B11B1C262E80 alice@example.test
gpg-wks-client: key F8E558CDCE839C89D465E692C285B11B1C262E80 published for 'alice@example.test'
$ find openpgpkey | sort
openpgpkey
openpgpkey/example.test
openpgpkey/example.test/hu
openpgpkey/example.test/hu/kei1q4tipxxu1yj79k9kfukdhfy631xe
openpgpkey/example.test/policy
```

في الإعداد أعلاه لاحظ أن اسم الملف هو هاش الجزء الأول من البريد بترميز Z-Base-32 كما تحدده [مسودة WKD](https://datatracker.ietf.org/doc/draft-koch-openpgp-webkey-service/?ref=arabroot.io)، وأن المجلد الناتج تضعه كما هو تحت `/.well-known/` في سيرفر الويب للنطاق الفرعي `openpgpkey`، وهي الطريقة المتقدمة Advanced Method، أو مباشرة على النطاق الرئيسي في الطريقة المباشرة Direct Method مع مسار دون اسم النطاق.

**ارفعه إلى keys.openpgp.org** بالأمر التالي، ثم افتح الرسالة التي تصلك وأكد البريد، فبدون هذا التأكيد لن يظهر اسمك وبريدك لمن يبحث عنك، كما يشرح [دليل السيرفر](https://keys.openpgp.org/about/usage-gnupg?ref=arabroot.io). ولم ننفذ هذا الأمر في التجربة، لأن السيرفر عام ولا مكان فيه لمفاتيح تجريبية:

```bash
gpg --keyserver hkps://keys.openpgp.org --send-keys F8E558CDCE839C89D465E692C285B11B1C262E80
```

## استيراد مفتاح غيرك والتحقق من بصمته

الآن ننتقل إلى Bob، وصله ملف `alice.asc` فاستورده ثم عرض بصمته:

```text
$ gpg --import /lab/shared/alice.asc
gpg: key C285B11B1C262E80: public key "Alice Example <alice@example.test>" imported
gpg: Total number processed: 1
gpg:               imported: 1

$ gpg --fingerprint alice@example.test
pub   ed25519 2026-10-09 [SC] [expires: 2028-10-08]
      F8E5 58CD CE83 9C89 D465  E692 C285 B11B 1C26 2E80
uid           [ unknown] Alice Example <alice@example.test>
sub   cv25519 2026-10-09 [E] [expires: 2028-10-08]
```

لاحظ الكلمة `[ unknown]`: المفتاح موجود عند Bob، ولكن GPG لا يعرف هل هو لAlice فعلاً. ولو حاول Bob أن يشفر لها الآن في الوضع الآلي فسوف يرفض GPG:

```text
$ gpg --batch --armor --encrypt --recipient alice@example.test report.txt
gpg: 7220124A948A4F79: There is no assurance this key belongs to the named user
gpg: report.txt: encryption failed: Unusable public key
```

والحل الصحيح ليس أن تجبره، وإنما أن تتحقق: يتصل Bob بAlice، أو يقابلها، وتقرأ له بصمتها من جهازها، فإذا طابقت البصمة التي عنده، يوقع على مفتاحها توقيعاً محلياً Local Signature لا يخرج من جهازه، ومعناه «أنا تحققت من هذا المفتاح بنفسي»:

```text
$ gpg --batch --pinentry-mode loopback --passphrase bob-lab-pass --quick-lsign-key F8E558CDCE839C89D465E692C285B11B1C262E80
pub  ed25519/C285B11B1C262E80
     created: 2026-10-09  expires: 2028-10-08  usage: SC
     trust: unknown       validity: unknown
 Primary key fingerprint: F8E5 58CD CE83 9C89 D465  E692 C285 B11B 1C26 2E80

     Alice Example <alice@example.test>

This key is due to expire on 2028-10-08.

The signature will be marked as non-exportable.

$ gpg -k alice@example.test
pub   ed25519 2026-10-09 [SC] [expires: 2028-10-08]
      F8E558CDCE839C89D465E692C285B11B1C262E80
uid           [  full  ] Alice Example <alice@example.test>
sub   cv25519 2026-10-09 [E] [expires: 2028-10-08]
```

صارت الصلاحية `[ full ]`، ومن الآن يقبل GPG التشفير لهذا المفتاح. والفرق بين `--quick-lsign-key` و`--quick-sign-key` أن الثاني توقيع قابل للتصدير يراه الآخرون إذا نشرت مفتاح Alice بعد توقيعك، وهذا ما كان يستخدم في شبكة الثقة، أما المحلي فيكفيك أنت ولا يكشف علاقتك بأحد.

## تشفير الملفات وفك تشفيرها

يشفر Bob ملفاً لAlice بالأمر `--encrypt` مع `--recipient`، والخيار `--armor` يجعل الناتج نصاً يمكن لصقه في رسالة:

```text
$ printf "Q3 budget: 120k\nMeeting moved to Sunday.\n" > report.txt
$ gpg --armor --encrypt --recipient alice@example.test report.txt
$ cat report.txt.asc
-----BEGIN PGP MESSAGE-----

hF4DciASSpSKT3kSAQdAc4TN4vf7R5hMfXc7fvHwv/Sfg37s/eAArlFMDdcotj0w
PuGmOF6ta7bYVTje5bz7zZbXLFYHpaf+/LuqUG3/U97TIGRU4Nf/jKtk/U6kRoks
0m4Bp51wbULIpWodjv2uTDllpgnCT53Qe8PscMOqhF5DS4dVupi8s513Y0EofsWh
QRfAMdl3wblDg2h34vEaPh6i4B1FqJPE383a4SzCKek4KvmnbNKxZzrNudvwbljy
rLkSvwmECO0vBgm+Cnpa0g==
=4cdN
-----END PGP MESSAGE-----
```

وتفكه Alice بالأمر `--decrypt`، والمخرج سوف يكون كما يلي:

```text
$ gpg --batch --pinentry-mode loopback --passphrase alice-lab-pass --decrypt /lab/shared/report.txt.asc
gpg: encrypted with cv25519 key, ID 7220124A948A4F79, created 2026-10-09
      "Alice Example <alice@example.test>"
Q3 budget: 120k
Meeting moved to Sunday.
```

ولاحظ أن Bob لا يستطيع أن يفك الملف الذي شفره بنفسه، لأنه شفره لمفتاح Alice فقط، فإذا أردت أن تحتفظ بنسخة تقرؤها أنت أيضاً فأضف نفسك مستلماً ثانياً `--recipient bob@example.test`، أو ضع في ملف الإعداد `gpg.conf` السطر `encrypt-to` مع بصمتك.

وفي الغالب تريد أن تشفر وتوقع معاً، حتى يعرف المستلم أن الرسالة منك وليست من أي شخص يملك مفتاحه العام، وهذا مثال من Alice إلى Bob بعد أن تحققت من مفتاحه:

```text
$ gpg --batch --pinentry-mode loopback --passphrase alice-lab-pass --sign --encrypt --armor -r bob@example.test reply.txt
```

وعند Bob يظهر النص ثم نتيجة التحقق من التوقيع:

```text
$ gpg --batch --pinentry-mode loopback --passphrase bob-lab-pass --decrypt /lab/shared/reply.txt.asc
gpg: encrypted with cv25519 key, ID 380BCF94EF97A3CC, created 2026-10-09
      "Bob Example <bob@example.test>"
The new VPN password is in the vault.
gpg: Signature made Fri Oct  9 13:12:31 2026 UTC
gpg:                using EDDSA key F8E558CDCE839C89D465E692C285B11B1C262E80
gpg: Good signature from "Alice Example <alice@example.test>" [full]
```

## توقيع الملفات والتحقق منها

للتوقيع ثلاثة أشكال، ولكل منها استخدام:

- **التوقيع المنفصل Detached Signature** بالأمر `--detach-sign`: ملف توقيع مستقل بجانب الملف الأصلي، وهو الشكل المستخدم في ملفات الإصدارات، لأن الملف الأصلي يبقى كما هو.
- **التوقيع المقروء Clearsign** بالأمر `--clearsign`: النص يبقى مقروءاً وحوله التوقيع، وهو مناسب لإعلان أو رسالة نصية، وهو شكل ملف `InRelease` في مستودعات Debian.
- **التوقيع المدمج** بالأمر `--sign`: الملف والتوقيع في ملف واحد مضغوط غير مقروء، وهو الأقل استخداماً اليوم.

توقع Alice ملف ملاحظات إصدار توقيعاً منفصلاً:

```text
$ gpg --batch --pinentry-mode loopback --passphrase alice-lab-pass --armor --detach-sign release-notes.txt
$ ls -l release-notes.txt*
-rw-r--r-- 1 root root  45 Oct  9 13:11 release-notes.txt
-rw-r--r-- 1 root root 228 Oct  9 13:11 release-notes.txt.asc
$ cat release-notes.txt.asc
-----BEGIN PGP SIGNATURE-----

iHUEABYKAB0WIQT45VjNzoOcidRl5pLChbEbHCYugAUCasjoGQAKCRDChbEbHCYu
gKMCAP9cFdQjf0PPFFNUGXMs+eHUmpviitnkvAN4UlpYQYe3lgD/VtmXjGhL72A4
U/Xa1lhd9JYJK65KwSYEdpZJDRq5vAY=
=ITzN
-----END PGP SIGNATURE-----
```

ويتحقق Bob منه، ثم يغير حرفاً في الملف ويتحقق مرة أخرى:

```text
$ gpg --verify release-notes.txt.asc release-notes.txt
gpg: Signature made Fri Oct  9 13:11:53 2026 UTC
gpg:                using EDDSA key F8E558CDCE839C89D465E692C285B11B1C262E80
gpg: Good signature from "Alice Example <alice@example.test>" [full]

$ sed -i "s/v1.4.0/v1.4.1/" release-notes.txt
$ gpg --verify release-notes.txt.asc release-notes.txt
gpg: Signature made Fri Oct  9 13:11:53 2026 UTC
gpg:                using EDDSA key F8E558CDCE839C89D465E692C285B11B1C262E80
gpg: BAD signature from "Alice Example <alice@example.test>" [full]
```

وفي السكربتات لا تقرأ النص، وإنما رمز الخروج Exit Code: الأمر `gpg --verify` أعاد 0 في الحالة الأولى و1 في الحالة الثانية في تجربتنا. وانتبه أن رمز 0 يعني أن التوقيع سليم من أي مفتاح موجود في حلقة مفاتيحك، فالسكربت الآمن يتحقق بحلقة مفاتيح لا يوجد فيها إلا المفتاح المتوقع، كما سنرى في قسم التحقق من ملف منزل.

وأما التوقيع المقروء فهذا شكله:

```text
$ gpg --batch --pinentry-mode loopback --passphrase alice-lab-pass --clearsign notice.txt
$ cat notice.txt.asc
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

We moved the backup window to 02:00.
-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQT45VjNzoOcidRl5pLChbEbHCYugAUCasjoLQAKCRDChbEbHCYu
gCUJAQCPWXr6cI0ojuDQLmlYAV7vRlssQaOfsYNnfaqIIwa9jgEA8U88o7qmLSgu
y4j3weTDYGDZl25azGp2aISmySloogk=
=9yqp
-----END PGP SIGNATURE-----
```

ويتحقق منه Bob بالأمر `gpg --verify notice.txt.asc` دون ملف ثان، لأن النص داخله.

## تشفير البريد في Thunderbird

منذ الإصدار 78 في عام 2020 صار [دعم OpenPGP مدمجاً في Thunderbird](https://wiki.mozilla.org/Thunderbird:OpenPGP?ref=arabroot.io) عبر مكتبة RNP، فلا تحتاج أن تثبت GnuPG ولا إضافة Enigmail القديمة. والخطوات باختصار:

1. افتح إعدادات الحساب Account Settings، ثم القسم End-To-End Encryption.
2. أنشئ مفتاحاً جديداً من هناك، أو استورد مفتاحك الذي أنشأته بـ GPG بعد تصديره بالأمر `gpg --armor --export-secret-keys` كما سيأتي في قسم النسخ الاحتياطي.
3. استورد المفاتيح العامة لمن تراسلهم، وغير حالة كل مفتاح إلى «Accepted (verified)» بعد أن تقارن البصمة معه، فهذا هو المقابل لما فعلناه بالأمر `--quick-lsign-key`.
4. عند كتابة رسالة فعل التشفير من زر Encrypt في نافذة الكتابة.

ولاحظ أن Thunderbird يحفظ المفاتيح في مخزنه الخاص وليس في GnuPG، لذلك إذا كانت مفاتيحك الخاصة على بطاقة ذكية أو YubiKey فعليك أن تفعل الخيار `mail.openpgp.allow_external_gnupg` من محرر الإعدادات المتقدمة، كما يشرح [دليل البطاقات الذكية في Thunderbird](https://wiki.mozilla.org/Thunderbird:OpenPGP:Smartcards?ref=arabroot.io)، حتى يستخدم GnuPG المثبت على جهازك عند الحاجة. و[بحسب صفحة الحالة](https://wiki.mozilla.org/Thunderbird:OpenPGP:Status?ref=arabroot.io) فإن Thunderbird يشفر عنوان الرسالة Subject افتراضياً، ولكن بقية الترويسات تبقى ظاهرة كما شرحنا في مقال الشرح. ولم نثبت Thunderbird في هذه التجربة، فهذه الخطوات من توثيقه.

## توقيع Git Commits والوسوم

اسم الكاتب وبريده في ال Commit مجرد نص، وأي شخص يستطيع أن يكتب اسمك، وهذا ما فعله Bob في تجربتنا على نسخة من مستودع Alice:

```text
$ git -c user.name="Alice Example" -c user.email=alice@example.test commit -q -am "Fix typo"
$ git log --format="%h %an <%ae> %G? %s"
7af029f Alice Example <alice@example.test> N Fix typo
f728666 Alice Example <alice@example.test> G Add README
```

الحرف بعد البريد هو حالة التوقيع من `%G?`: الحرف `G` يعني توقيعاً سليماً، و`N` يعني أنه لا يوجد توقيع. فال Commit الأول كتبته Alice ووقعته، والثاني كتبه Bob باسمها وفيه سطر يحمل كوداً من موقع خارجي، والفرق الوحيد الظاهر بينهما هو التوقيع. وإعداد التوقيع عند Alice كان كما يلي:

```bash
git config user.name "Alice Example"
git config user.email alice@example.test
git config user.signingkey F8E558CDCE839C89D465E692C285B11B1C262E80
git config commit.gpgsign true
git config tag.gpgSign true
```

في الإعداد أعلاه لاحظ التالي:

- `user.signingkey` يحدد المفتاح بالبصمة الكاملة، و[بحسب توثيق git-config](https://git-scm.com/docs/git-config?ref=arabroot.io) فهذه القيمة تمرر كما هي إلى الخيار `--local-user` في gpg.
- `commit.gpgsign` و`tag.gpgSign` يجعلان كل Commit وكل وسم موقعاً دون أن تكتب `-S` كل مرة.
- البريد في `user.email` يجب أن يطابق بريداً في مفتاحك، لأن منصات مثل GitHub لا تعرض علامة Verified إلا إذا تطابق، وعليك أن ترفع مفتاحك العام إلى حسابك فيها.
- في التجربة فقط أضفنا `gpg.program` يشير إلى سكربت صغير يمرر كلمة المرور، لأن Git كان يعمل دون طرفية، وعلى جهازك لا تحتاجه.

ثم أنشأت Alice Commit ووسماً، وتحققت منهما:

```text
$ git commit -q -m "Add README"
$ git tag -m "first release" v0.1.0
$ git log --show-signature -1
commit f7286661542d5f269e9d0719e0d81919232899ea
gpg: Signature made Fri Oct  9 13:12:51 2026 UTC
gpg:                using EDDSA key F8E558CDCE839C89D465E692C285B11B1C262E80
gpg: Good signature from "Alice Example <alice@example.test>" [ultimate]
Author: Alice Example <alice@example.test>
Date:   Fri Oct 9 13:12:51 2026 +0000

    Add README
$ git verify-tag v0.1.0
gpg: Signature made Fri Oct  9 13:12:51 2026 UTC
gpg:                using EDDSA key F8E558CDCE839C89D465E692C285B11B1C262E80
gpg: Good signature from "Alice Example <alice@example.test>" [ultimate]
```

وقد يتساءل البعض: لماذا لا أوقع بمفتاح SSH الذي أستخدمه أصلاً للدفع إلى المستودع؟ والإجابة أن هذا ممكن منذ أن أضاف Git القيمة `ssh` للإعداد `gpg.format`، وقد ذكرناه مع مفاتيح الأمان في [مقال Passkeys](https://arabroot.io/articles/%D8%A7%D9%84%D8%AF%D8%AE%D9%88%D9%84-%D8%AF%D9%88%D9%86-%D9%83%D9%84%D9%85%D8%A9-%D9%85%D8%B1%D9%88%D8%B1-passkeys-%D9%88-fido2/)، والمقارنة الكاملة بين الطريقتين ومتى تختار كلاً منهما موضوع مقال قادم بإذن الله في مرحلة Git من خارطة الطريق.

## التحقق من ملف منزل: مثال Debian

هذا هو الاستخدام الذي سوف تحتاجه أكثر من أي شيء آخر، والصورة التالية تبين خطواته:

![خمس خطوات: تنزيل قائمة الهاش SHA256SUMS وتوقيعها، ثم أخذ المفتاح من صفحة debian.org الرسمية، ثم مقارنة البصمة بالمكتوبة في الصفحة، ثم التحقق من التوقيع، ثم مقارنة هاش ملف ISO بالقائمة](https://arabroot.io/content/images/2026/10/gpg-practice-02-verify-download.webp)

التوقيع يحمي قائمة الهاش، والهاش يحمي الملف الكبير

نزل Bob قائمة الهاش وتوقيعها لملفات Debian 13.7، وحاول التحقق قبل أن يملك المفتاح:

```text
$ curl -sSfLO https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/SHA256SUMS
$ curl -sSfLO https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/SHA256SUMS.sign
$ cat SHA256SUMS
a7ef94ac2fb9a7fec454552abd629b7cc9d5155c886165a45649f5ce6167e355  debian-13.7.0-amd64-netinst.iso
d33ed0c64bde5ff43445c0c530f9da599954d8585771c55345cb840d7997d4a7  debian-edu-13.7.0-amd64-netinst.iso
d6d4e0d038936230229a66b7c1765452e73c72a962e79dbb99544882295271e8  debian-mac-13.7.0-amd64-netinst.iso
$ gpg --verify SHA256SUMS.sign SHA256SUMS
gpg: Signature made Sat Sep 12 16:20:46 2026 UTC
gpg:                using RSA key DF9B9C49EAA9298432589D76DA87E80D6294BE9B
gpg: Can't check signature: No public key
```

الخطأ `No public key` هنا طبيعي، ومعناه أن التوقيع من مفتاح بصمته `DF9B9C49...` وهو غير موجود عند Bob. والخطأ الذي يقع فيه كثيرون أن يبحثوا عن هذه البصمة في سيرفر مفاتيح ويستوردوا أول نتيجة، والصحيح أن تأخذ المفتاح من مصدر رسمي تعرفه، وهنا [صفحة التحقق في موقع Debian](https://www.debian.org/CD/verify?ref=arabroot.io) التي تكتب البصمات كاملة وتضع رابطاً لكل مفتاح:

```text
$ curl -sSfL -o debian-cd-key.asc https://www.debian.org/CD/key-DA87E80D6294BE9B.txt
$ gpg --show-keys --fingerprint debian-cd-key.asc
pub   rsa4096 2011-01-05 [SC]
      DF9B 9C49 EAA9 2984 3258  9D76 DA87 E80D 6294 BE9B
uid                      Debian CD signing key <debian-cd@lists.debian.org>
sub   rsa4096 2011-01-05 [E]
```

الأمر `--show-keys` يعرض المفتاح دون أن يستورده، فتقارن البصمة `DF9B 9C49 EAA9 2984 3258 9D76 DA87 E80D 6294 BE9B` بالمكتوبة في الصفحة، وقد طابقت، ثم تستورده وتتحقق:

```text
$ gpg --import debian-cd-key.asc
$ gpg --verify SHA256SUMS.sign SHA256SUMS
gpg: Signature made Sat Sep 12 16:20:46 2026 UTC
gpg:                using RSA key DF9B9C49EAA9298432589D76DA87E80D6294BE9B
gpg: Good signature from "Debian CD signing key <debian-cd@lists.debian.org>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: DF9B 9C49 EAA9 2984 3258  9D76 DA87 E80D 6294 BE9B
```

والتحذير هنا متوقع، لأنك لم توقع على مفتاح Debian، والمهم أن البصمة في آخر سطر هي نفسها التي تحققت منها من الصفحة الرسمية. وبعد ذلك تبقى الخطوة الأخيرة التي ينساها كثيرون: أن تقارن هاش ملف ISO الذي نزلته بالقائمة الموقعة، بالأمر `sha256sum -c SHA256SUMS --ignore-missing` في المجلد الذي فيه الملف، فالتوقيع يحمي القائمة فقط. ولم ننزل ملف ISO نفسه في التجربة لأن الفكرة واضحة دونه.

وفي السكربتات والخطوط الآلية لا تستخدم حلقة مفاتيحك الشخصية، وإنما أداة تتحقق بحلقة مفاتيح فيها المفتاح المتوقع وحده، فإذا كان التوقيع من أي مفتاح آخر فشل التحقق. والأداة التقليدية لهذا هي `gpgv`، ولكنها لم تكن مثبتة في Container التجربة من Debian 13 رغم تثبيت gnupg، بينما كانت `sqv` موجودة لأن apt نفسه يعتمد عليها، فاستخدمناها مع ملف المفتاح بالصيغة الثنائية:

```text
$ gpg --dearmor < debian-cd-key.asc > debian-cd.gpg
$ sqv --keyring debian-cd.gpg SHA256SUMS.sign SHA256SUMS
DF9B9C49EAA9298432589D76DA87E80D6294BE9B
$ echo $?
0

$ sed -i "s/^a7ef/b7ef/" SHA256SUMS
$ sqv --keyring debian-cd.gpg SHA256SUMS.sign SHA256SUMS
Verifying signature:
           Message has been manipulated
$ echo $?
1
```

لاحظ أن `sqv` يطبع بصمة المفتاح الذي وقع عند النجاح ويعيد 0، ويرفض القائمة التي غيرنا فيها حرفاً واحداً ويعيد 1، وهذا كل ما يحتاجه سكربت.

## النسخ الاحتياطي ونقل المفتاح إلى جهاز جديد

إذا ضاع المفتاح الخاص دون نسخة احتياطية فلن تستطيع فك أي رسالة شفرت لك به، أبداً، فلا يوجد «نسيت كلمة المرور» في GPG. والنسخة الاحتياطية تتكون من ملفين: المفتاح الخاص مع كل أجزائه، وقاعدة الثقة Owner Trust التي تحفظ ثقتك بالمفاتيح:

```text
$ gpg --batch --pinentry-mode loopback --passphrase alice-lab-pass --armor --export-secret-keys alice@example.test > alice-secret.asc
$ gpg --export-ownertrust > alice-ownertrust.txt
$ head -2 alice-secret.asc
-----BEGIN PGP PRIVATE KEY BLOCK-----

$ cat alice-ownertrust.txt
# List of assigned trustvalues, created Fri Oct  9 13:13:54 2026 UTC
# (Use "gpg --import-ownertrust" to restore them)
F8E558CDCE839C89D465E692C285B11B1C262E80:6:
```

والمفتاح الخاص في الملف المصدر يبقى محمياً بكلمة المرور نفسها، ومع ذلك عامله كأثمن ملف تملكه: لا ترفعه إلى خدمة تخزين سحابية دون تشفير إضافي، ولا ترسله بالبريد. ثم على الجهاز الجديد، وهو المجلد `alice-laptop` في تجربتنا:

```text
$ gpg --batch --pinentry-mode loopback --passphrase alice-lab-pass --import /lab/shared/alice-secret.asc
gpg: keybox '/lab/alice-laptop/pubring.kbx' created
gpg: /lab/alice-laptop/trustdb.gpg: trustdb created
gpg: key C285B11B1C262E80: public key "Alice Example <alice@example.test>" imported
gpg: key C285B11B1C262E80: secret key imported
gpg: Total number processed: 1
gpg:               imported: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1
$ gpg --import-ownertrust /lab/shared/alice-ownertrust.txt
gpg: inserting ownertrust of 6
$ gpg -K
/lab/alice-laptop/pubring.kbx
-----------------------------
sec   ed25519 2026-10-09 [SC] [expires: 2028-10-08]
      F8E558CDCE839C89D465E692C285B11B1C262E80
uid           [ultimate] Alice Example <alice@example.test>
ssb   cv25519 2026-10-09 [E] [expires: 2028-10-08]
```

ظهر المفتاح الخاص `sec` والمفتاح الفرعي `ssb` بالبصمة نفسها، والثقة `[ultimate]` عادت كما كانت. ولا تنقل المجلد `~/.gnupg` كاملاً بين أنظمة مختلفة، لأن فيه ملفات Sockets وإعدادات خاصة بالجهاز، والتصدير والاستيراد هما الطريقة الآمنة.

## تمديد تاريخ الانتهاء

قبل أن يقترب تاريخ الانتهاء تمدده للمفتاح الرئيسي ثم للمفاتيح الفرعية، والنجمة `"*"` تعني كل المفاتيح الفرعية:

```text
$ gpg --batch --pinentry-mode loopback --passphrase alice-lab-pass --quick-set-expire F8E558CDCE839C89D465E692C285B11B1C262E80 3y
$ gpg --batch --pinentry-mode loopback --passphrase alice-lab-pass --quick-set-expire F8E558CDCE839C89D465E692C285B11B1C262E80 3y "*"
$ gpg -k alice@example.test
pub   ed25519 2026-10-09 [SC] [expires: 2029-10-08]
      F8E558CDCE839C89D465E692C285B11B1C262E80
uid           [ultimate] Alice Example <alice@example.test>
sub   cv25519 2026-10-09 [E] [expires: 2029-10-08]
```

ولاحظ أن المدة تحسب من تاريخ اليوم وليس من التاريخ القديم، فصار الانتهاء في 2029\. والتمديد لا يفيد الآخرين حتى يحصلوا على النسخة الجديدة من مفتاحك العام، فتصدره مرة أخرى وتنشره، وعندما استوردها Bob ظهر له أنها توقيعات جديدة على المفتاح نفسه:

```text
$ gpg --import /lab/shared/alice.asc
gpg: key C285B11B1C262E80: "Alice Example <alice@example.test>" 2 new signatures
gpg: Total number processed: 1
gpg:         new signatures: 2
```

## إلغاء المفتاح عند سرقته أو فقده

إذا سرق الجهاز أو شككت أن المفتاح الخاص تسرب، فاستورد شهادة الإلغاء في حلقة مفاتيحك ثم انشر المفتاح الملغى بالطريقة نفسها التي نشرته بها. وفي تجربتنا استوردت Carol الشهادة التي أعدتها Alice مسبقاً:

```text
$ gpg --import /lab/shared/alice-revoke.asc
gpg: key C285B11B1C262E80: "Alice Example <alice@example.test>" revocation certificate imported
gpg: Total number processed: 1
gpg:    new key revocations: 1
$ gpg -k alice@example.test
pub   ed25519 2026-10-09 [SC] [revoked: 2026-10-09]
      F8E558CDCE839C89D465E692C285B11B1C262E80
uid           [ revoked] Alice Example <alice@example.test>

$ gpg --auto-key-locate local --encrypt -r alice@example.test -o /dev/null /lab/shared/release-notes.txt
gpg: alice@example.test: skipped: No public key
gpg: /lab/shared/release-notes.txt: encryption failed: No public key
```

ومن الآن ترفض Carol التشفير لهذا المفتاح، وأي توقيع قديم منه يظهر معه تحذير الإلغاء والسبب، كما رأينا في مقال الشرح. وإذا كان المفتاح على keys.openpgp.org فارفع النسخة الملغاة بالأمر `--send-keys` نفسه الذي رفعته به، وإذا كان على WKD فاستبدل الملف في المجلد بالنسخة الملغاة.

## مفاتيح الأمان YubiKey والبطاقات الذكية

أقوى حماية للمفتاح الخاص ألا يكون على القرص أصلاً، فمفاتيح الأمان التي تدعم OpenPGP، مثل [YubiKey](https://developers.yubico.com/PGP/?ref=arabroot.io) وNitrokey، تحفظ المفاتيح الفرعية داخل شريحة لا تسمح بتصديرها، ويتم التوقيع وفك التشفير داخل المفتاح نفسه بعد أن تكتب رقمه السري PIN. والطريقة الشائعة أن تنشئ المفتاح على جهاز آمن، وتأخذ منه نسخة احتياطية كما في القسم السابق، ثم تنقل المفاتيح الفرعية إلى البطاقة بالأمر `gpg --edit-key` ثم الأمر `keytocard` داخله، وتبقى البطاقة عندك كمفتاح البيت. وأوامر البطاقة تمر عبر برنامج `scdaemon`، فإذا لم يكن مثبتاً أو لم تكن البطاقة موصولة فسوف ترى رسالة مثل التي ظهرت في Container التجربة، الذي لم نثبت فيه هذا البرنامج ولم نصل به أي جهاز:

```text
$ gpg --card-status
gpg: error getting version from 'scdaemon': No SmartCard daemon
gpg: OpenPGP card not available: No SmartCard daemon
```

وفي Debian وUbuntu تثبت البرنامج بالحزمة `scdaemon`. وقد شرحنا الفرق بين طرازات مفاتيح الأمان وما يدعمه كل منها في [مقال Passkeys](https://arabroot.io/articles/%D8%A7%D9%84%D8%AF%D8%AE%D9%88%D9%84-%D8%AF%D9%88%D9%86-%D9%83%D9%84%D9%85%D8%A9-%D9%85%D8%B1%D9%88%D8%B1-passkeys-%D9%88-fido2/)، وانتبه عند الشراء أن السلسلة التي تدعم FIDO فقط من بعض الشركات لا تدعم OpenPGP.

## الأخطاء الشائعة وكيف تقرؤها

وفيما يلي الأخطاء التي ظهرت لنا في التجربة، وكلها رسائل حقيقية:

- **`Can't check signature: No public key` عند التحقق:** المفتاح الذي وقع غير موجود عندك، فخذ البصمة من سطر `using RSA key` وابحث عن المفتاح في المصدر الرسمي للمشروع، ولا تستورد أول نتيجة من سيرفر مفاتيح.
- **`There is no assurance this key belongs to the named user` ثم `Unusable public key` عند التشفير:** المفتاح موجود ولكنك لم تتحقق منه، فقارن البصمة مع صاحبها ثم وقعه بالأمر `--quick-lsign-key`. ولا تستخدم `--trust-model always` لتتجاوزه، لأنك بهذا تلغي الحماية الوحيدة من المفتاح المزيف.
- **`new key but contains no user ID - skipped` عند الاستيراد من keys.openpgp.org:** صاحب المفتاح لم يؤكد بريده على السيرفر، فلا يعطيك السيرفر إلا المفتاح دون هوية، وGnuPG يرفضه. خذ المفتاح من مصدر آخر رسمي، أو اطلب من صاحبه أن يؤكد بريده.
- **`BAD signature`:** الملف تغير بعد توقيعه، أو أنك تتحقق من الملف الخطأ، فنزله من جديد من المصدر الرسمي ولا تستخدمه حتى ينجح التحقق.
- **`WARNING: This key is not certified with a trusted signature!` مع `Good signature`:** التوقيع سليم، ولكنك لم تتحقق من المفتاح، فقارن البصمة المطبوعة في آخر سطر بالمصدر الرسمي، وإذا كان هذا المفتاح سوف يتكرر عندك فوقعه توقيعاً محلياً.

**`Inappropriate ioctl for device` عند التوقيع أو فك التشفير:** pinentry يحاول أن يسألك عن كلمة المرور ولا يعرف أي طرفية يستخدم، وهذا يحدث كثيراً داخل SSH أو tmux أو مع Git. وهذا ما ظهر لنا عندما وقعنا من Container دون طرفية:

```text
$ gpg --clearsign t.txt
gpg: signing failed: Inappropriate ioctl for device
gpg: t.txt: clear-sign failed: Inappropriate ioctl for device
```

والحل كما في [توثيق gpg-agent](https://www.gnupg.org/documentation/manuals/gnupg/Invoking-GPG%5F002dAGENT.html?ref=arabroot.io) أن تضيف إلى ملف `~/.bashrc` أو ما يقابله السطرين التاليين:

```bash
GPG_TTY=$(tty)
export GPG_TTY
```

وبعد أن ضبطنا المتغير في طرفية حقيقية ظهر مربع pinentry في الطرفية بالنص «Please enter the passphrase to unlock the OpenPGP secret key» ونجح التوقيع. وإذا بقيت المشكلة بعد تغيير الإعداد فأعد تشغيل الوكيل بالأمر `gpgconf --kill gpg-agent`.

**`skipped: No public key` عند التشفير مع أن المفتاح موجود:** قد يكون المفتاح منتهياً أو ملغى، فالرسالة نفسها ظهرت لنا في الحالتين. واعرض المفتاح بالأمر `gpg -k` وانظر إلى `[expired]` أو `[revoked]`، ثم اطلب من صاحبه النسخة الجديدة. وقد اختبرنا المفتاح المنتهي في التجربة دون انتظار سنتين بالخيار `--faked-system-time` الذي يجعل GPG يعمل بتاريخ آخر:

```text
$ gpg --faked-system-time 20290101T000000 --auto-key-locate local --armor --encrypt -r alice@example.test report.txt
gpg: WARNING: running with faked system time: 2029-01-01 00:00:00
gpg: alice@example.test: skipped: No public key
gpg: report.txt: encryption failed: No public key
```

ودون الخيار `--auto-key-locate local` حاول GPG من نفسه أن يبحث عن مفتاح صالح عبر WKD على نطاق البريد، وهذا ما ظهر لنا لأن النطاق `example.test` غير موجود:

```text
gpg: error retrieving 'alice@example.test' via WKD: Unknown host
gpg: alice@example.test: skipped: Unknown host
```

## إزالة التجربة

كل شيء كان داخل Container واحد بدأناه بالخيار `--rm`، فإيقافه يحذفه مع كل المفاتيح التجريبية، ثم نحذف ال Image التي بنيناها بالاسم:

```bash
docker stop lab-gpg-box
docker rmi lab-gpg-debian:13.7
```

## جدول الأوامر

| المهمة                           | الأمر                                                          |
| -------------------------------- | -------------------------------------------------------------- |
| إنشاء مفتاح رئيسي                | gpg --quick-gen-key "Name <mail>" ed25519 sign,cert 2y         |
| إضافة مفتاح تشفير فرعي           | gpg --quick-add-key FPR cv25519 encr 2y                        |
| عرض المفاتيح بالبصمات            | gpg -K --keyid-format long --with-subkey-fingerprints          |
| شهادة إلغاء بسبب                 | gpg --output revoke.asc --gen-revoke FPR                       |
| تصدير المفتاح العام              | gpg --armor --export mail > key.asc                            |
| رفع المفتاح إلى keys.openpgp.org | gpg --keyserver hkps://keys.openpgp.org --send-keys FPR        |
| استيراد مفتاح وعرض بصمته         | gpg --import key.asc ثم gpg --fingerprint mail                 |
| عرض مفتاح دون استيراده           | gpg --show-keys --fingerprint key.asc                          |
| توقيع محلي بعد التحقق            | gpg --quick-lsign-key FPR                                      |
| تشفير ملف                        | gpg --armor --encrypt -r mail file                             |
| تشفير وتوقيع                     | gpg --sign --encrypt --armor -r mail file                      |
| فك التشفير                       | gpg --decrypt file.asc                                         |
| توقيع منفصل والتحقق منه          | gpg --armor --detach-sign file ثم gpg --verify file.asc file   |
| توقيع مقروء                      | gpg --clearsign file                                           |
| توقيع Git                        | git config user.signingkey FPR وgit config commit.gpgsign true |
| التحقق في Git                    | git log --show-signature وgit verify-tag v1.0                  |
| نسخة احتياطية                    | gpg --armor --export-secret-keys mail وgpg --export-ownertrust |
| تمديد الانتهاء                   | gpg --quick-set-expire FPR 2y ثم الأمر نفسه مع "\*"            |

## تدريب عملي

1. أنشئ مفتاحاً بالأوامر أعلاه في مجلد تجريبي بالمتغير `GNUPGHOME`، واعرضه، وتأكد أن للمفتاح الرئيسي والفرعي تاريخ انتهاء، ثم انقل شهادة الإلغاء إلى مكان آخر.
2. نزل قائمة الهاش وتوقيعها لأي توزيعة تستخدمها، وابحث في موقعها الرسمي عن بصمة مفتاح التوقيع، وتحقق من القائمة ثم من ملف ISO نفسه.
3. فعل توقيع ال Commits في مستودع تجريبي، وأنشئ Commit موقعاً وآخر غير موقع، وانظر إلى الفرق في `git log --format="%h %G? %s"`.

## الخلاصة

وصلنا لنهاية الموضوع، وأهم ما فيه:

- ثبت GnuPG من توزيعتك على Linux، أو من Homebrew أو GPG Suite على macOS، أو Gpg4win مع Kleopatra على Windows.
- أنشئ المفتاح بأمرين صريحين: مفتاح رئيسي ed25519 ومفتاح تشفير فرعي cv25519، ولكل منهما تاريخ انتهاء، وانظر إلى المخرج دائماً.
- انقل شهادة الإلغاء والنسخة الاحتياطية من المفتاح الخاص إلى مكان آمن بعيداً عن الجهاز اليوم وليس غداً.
- لا تشفر لمفتاح ولا تثق بتوقيع حتى تقارن البصمة الكاملة عبر قناة أخرى، ثم وقع المفتاح توقيعاً محلياً.
- عند التحقق من ملف منزل خذ المفتاح من الصفحة الرسمية لا من المرآة، وتحقق من التوقيع ثم من هاش الملف نفسه، وفي السكربتات استخدم حلقة مفاتيح فيها المفتاح المتوقع وحده.
- وقع Git Commits والوسوم بإعداد `user.signingkey` و`commit.gpgsign`، فاسم الكاتب وحده يستطيع أي أحد أن يكتبه.
- أغلب أخطاء GPG تقرأ مباشرة: مفتاح غير موجود، أو غير متحقق منه، أو منته، أو pinentry دون طرفية يحله `GPG_TTY`.

[![](https://arabroot.io/content/images/2026/10/gpg-basics-cover-cover.webp)دليلGPG وOpenPGP: شرح التشفير والتوقيع بالمفتاح العامكيف يعمل GPG بالمفتاح العام والخاص، ولماذا تقارن البصمة دائماً، وأين يحميك اليوم وأين لا يحميك.](https://arabroot.io/articles/%D8%B4%D8%B1%D8%AD-gpg-%D9%88-openpgp-%D8%A7%D9%84%D8%AA%D8%B4%D9%81%D9%8A%D8%B1-%D9%88%D8%A7%D9%84%D8%AA%D9%88%D9%82%D9%8A%D8%B9-%D8%A8%D8%A7%D9%84%D9%85%D9%81%D8%AA%D8%A7%D8%AD-%D8%A7%D9%84%D8%B9%D8%A7%D9%85/)[![](https://arabroot.io/content/images/2026/10/crypto-for-devs-cover-cover.webp)دليلالتشفير للمطورين: ماذا تستخدم ولماذا لا تخترع خوارزميتكأي هاش تستخدم لكلمات المرور، ومتى تحتاج التشفير المتماثل أو غير المتماثل، وأين تحفظ المفاتيح بأمان في تطبيقك.](https://arabroot.io/articles/%D8%A7%D9%84%D8%AA%D8%B4%D9%81%D9%8A%D8%B1-%D9%84%D9%84%D9%85%D8%B7%D9%88%D8%B1%D9%8A%D9%86-%D8%A7%D9%84%D9%87%D8%A7%D8%B4-%D9%88%D9%83%D9%84%D9%85%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B1%D9%88%D8%B1-%D9%88%D8%A7%D9%84%D9%85%D9%81%D8%A7%D8%AA%D9%8A%D8%AD/)[![](https://arabroot.io/content/images/2026/10/git-basics-cover-cover.webp)دليلإدارة النسخ وGit للمبتدئين: لماذا نحتاجها وكيف تعمللماذا تضيع الملفات بأسماء final\_v2 ويمسح الزملاء عمل بعضهم، وكيف يحل Git ذلك على مشروع حقيقي من أول commit.](https://arabroot.io/articles/%D8%A7%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D9%86%D8%B3%D8%AE-%D9%88-git-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86/)[![](https://arabroot.io/content/images/2026/10/passkeys-cover-cover.webp)دليلالدخول دون كلمة مرور: شرح Passkeys وWebAuthnلماذا لا تحميك رموز SMS وTOTP من التصيد الحديث، وكيف تحل Passkeys المشكلة بمفتاح خاص لا يغادر جهازك.](https://arabroot.io/articles/%D8%A7%D9%84%D8%AF%D8%AE%D9%88%D9%84-%D8%AF%D9%88%D9%86-%D9%83%D9%84%D9%85%D8%A9-%D9%85%D8%B1%D9%88%D8%B1-passkeys-%D9%88-fido2/)[![](https://arabroot.io/content/images/2026/10/supply-chain-cover-cover.webp)دليلأمن سلسلة التوريد البرمجية Software Supply Chain للمبتدئينكل ما بين كود غيرك وسيرفرك قد يحمل كود المهاجم، وهنا تعرف التهديدات الحقيقية بحوادث موثقة والدفاع المناسب لكل حلقة.](https://arabroot.io/articles/%D8%A7%D9%85%D9%86-%D8%B3%D9%84%D8%B3%D9%84%D8%A9-%D8%A7%D9%84%D8%AA%D9%88%D8%B1%D9%8A%D8%AF-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86/)

## سجل التحديثات

- أكتوبر 2026: كتابة المقال، وتنفيذ كل الأوامر في Container من debian:13.7-slim مع GnuPG 2.4.7 وGit 2.47.3 وsqv 1.3.0، بمفاتيح تجريبية لشخصيات وهمية على النطاق example.test، والتحقق من ملفات Debian 13.7 الرسمية.