This is an automated email from the git hooks/post-receive script. guillem pushed a commit to branch main in repository dpkg.
View the commit online: https://git.dpkg.org/cgit/dpkg/dpkg.git/commit/?id=0eb367fb4eacc28885c365907e0707df237c80a2 commit 0eb367fb4eacc28885c365907e0707df237c80a2 Author: Daniel Kahn Gillmor <[email protected]> AuthorDate: Wed Oct 26 10:12:48 2022 +0200 Dpkg::OpenPGP: Add native helpers for ASCII Armor These functions prepare us to remove reliance on «gpg», which was only used for armoring and dearmoring while using «gpgv». [[email protected]: - Coding style and formatting fixes. - Remove C code in comments. - Split base64 lines at 64 characters. - Match on same whitespace as Dpkg::Control::HashCore parsing. - Rename _pgp_unarmor_data() to _pgp_dearmor_data(). - Remove spurious EOLs. ] Ref: https://salsa.debian.org/debian/devscripts/-/merge_requests/286 Signed-off-by: Daniel Kahn Gillmor <[email protected]> Signed-off-by: Guillem Jover <[email protected]> --- scripts/Dpkg/OpenPGP.pm | 75 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/scripts/Dpkg/OpenPGP.pm b/scripts/Dpkg/OpenPGP.pm index dbe369913..25f369e78 100644 --- a/scripts/Dpkg/OpenPGP.pm +++ b/scripts/Dpkg/OpenPGP.pm @@ -20,6 +20,7 @@ use warnings; use POSIX qw(:sys_wait_h); use File::Temp; +use MIME::Base64; use Dpkg::Gettext; use Dpkg::ErrorHandling; @@ -44,6 +45,80 @@ sub is_armored { return $armored; } +# _pgp_* functions are strictly for applying or removing ASCII armor. +# See <https://datatracker.ietf.org/doc/html/rfc4880#section-6> for more +# details. +# +# Note that these _pgp_* functions are only necessary while relying on +# gpgv, and gpgv itself does not verify multiple signatures correctly +# (see https://bugs.debian.org/1010955). + +sub _pgp_dearmor_data { + my ($type, $data) = @_; + + # Note that we ignore an incorrect or absent checksum, following the + # guidance of + # <https://datatracker.ietf.org/doc/draft-ietf-openpgp-crypto-refresh/>. + my $armor_regex = qr{ + -----BEGIN\ PGP\ \Q$type\E-----[\r\t ]*\n + (?:[^:]+:\ [^\n]*[\r\t ]*\n)* + [\r\t ]*\n + ([a-zA-Z0-9/+\n]+={0,2})[\r\t ]*\n + (?:=[a-zA-Z0-9/+]{4}[\r\t ]*\n)? + -----END\ PGP\ \Q$type\E----- + }xm; + + if ($data =~ m/$armor_regex/) { + return decode_base64($1); + } + return; +} + +sub _pgp_armor_checksum { + my ($data) = @_; + + # From the upcoming revision to RFC 4880 + # <https://datatracker.ietf.org/doc/draft-ietf-openpgp-crypto-refresh/>. + # + # The resulting three-octet-wide value then gets base64-encoded into + # four base64 ASCII characters. + + my $CRC24_INIT = 0xB704CE; + my $CRC24_GENERATOR = 0x864CFB; + + my @bytes = unpack 'C*', $data; + my $crc = $CRC24_INIT; + for my $b (@bytes) { + $crc ^= ($b << 16); + for (1 .. 8) { + $crc <<= 1; + if ($crc & 0x1000000) { + # Clear bit 25 to avoid overflow. + $crc &= 0xffffff; + $crc ^= $CRC24_GENERATOR; + } + } + } + my $sum = pack 'CCC', ($crc >> 16) & 0xff, ($crc >> 8) & 0xff, $crc & 0xff; + return encode_base64($sum, q{}); +} + +sub _pgp_armor_data { + my ($type, $data) = @_; + + my $out = encode_base64($data, q{}) =~ s/(.{1,64})/$1\n/gr; + chomp $out; + my $crc = _pgp_armor_checksum($data); + my $armor = <<~"ARMOR"; + -----BEGIN PGP $type----- + + $out + =$crc + -----END PGP $type----- + ARMOR + return $armor; +} + sub _gpg_armor { my ($type, $sig, $asc) = @_; -- Dpkg.Org's dpkg

