@@ -478,6 +478,130 @@ install_cpython() {
478478 curl -sSL -o " /tmp/python-src/${cpython_tgz_filename} " " ${cpython_tgz_url} "
479479 fi
480480}
481+ # Get system architecture for downloads
482+ get_architecture () {
483+ local architecture=" "
484+ case $( uname -m) in
485+ x86_64) architecture=" amd64" ;;
486+ aarch64 | armv8* ) architecture=" arm64" ;;
487+ aarch32 | armv7* | armvhf* ) architecture=" armhf" ;;
488+ i? 86) architecture=" 386" ;;
489+ * ) echo " (!) Architecture $( uname -m) unsupported" ; exit 1 ;;
490+ esac
491+ echo ${architecture}
492+ }
493+
494+ # Install cosign with multi-distro support
495+ install_cosign () {
496+
497+ COSIGN_VERSION=" latest"
498+ local cosign_url=' https://github.com/sigstore/cosign'
499+ local architecture=$( get_architecture)
500+
501+ find_version_from_git_tags COSIGN_VERSION " ${cosign_url} "
502+
503+ # Remove 'v' prefix if present for download URL
504+ local version_for_url=" ${COSIGN_VERSION# v} "
505+
506+ local cosign_filename=" /tmp/cosign_${version_for_url} _${architecture} .deb"
507+ local cosign_url=" https://github.com/sigstore/cosign/releases/download/v${version_for_url} /cosign_${version_for_url} _${architecture} .deb"
508+
509+ echo " Downloading cosign from: ${cosign_url} "
510+
511+ if curl -L -f --fail-with-body " ${cosign_url} " -o " $cosign_filename " 2> /dev/null; then
512+ echo " (*) Successfully downloaded cosign v${COSIGN_VERSION} "
513+ else
514+ echo -e " \n(!) Failed to fetch cosign v${COSIGN_VERSION} ..."
515+ # Try previous version
516+ find_prev_version_from_git_tags COSIGN_VERSION " https://github.com/sigstore/cosign"
517+ echo -e " \nAttempting to install ${COSIGN_VERSION} "
518+
519+ version_for_url=" ${COSIGN_VERSION# v} "
520+ cosign_filename=" /tmp/cosign_${version_for_url} _${architecture} .deb"
521+ cosign_url=" https://github.com/sigstore/cosign/releases/download/v${version_for_url} /cosign_${version_for_url} _${architecture} .deb"
522+
523+ if ! curl -L -f --fail-with-body " ${cosign_url} " -o " $cosign_filename " 2> /dev/null; then
524+ echo " (!) Failed to download cosign v${COSIGN_VERSION} as fallback"
525+ return 1
526+ fi
527+ fi
528+
529+ # Install the package
530+ if [ -f " $cosign_filename " ]; then
531+ dpkg -i " $cosign_filename "
532+ rm " $cosign_filename "
533+ echo " Installation of cosign succeeded with ${COSIGN_VERSION} ."
534+ else
535+ echo " (!) Failed to download cosign package"
536+ return 1
537+ fi
538+
539+ }
540+
541+ # COSIGN signature verification for python versions >= 3.14
542+ cosign_verification () {
543+ local VERSION=" $1 "
544+
545+ # Ensure cosign is installed
546+ if ! type cosign > /dev/null 2>&1 ; then
547+ echo " (*) cosign not found, installing..."
548+ if ! install_cosign; then
549+ echo " (!) Failed to install cosign"
550+ return 1
551+ fi
552+ else
553+ echo " (*) cosign is already available on the system"
554+ fi
555+
556+ echo " (*) Attempting COSIGN verification for Python ${VERSION} ..."
557+
558+ # Check if COSIGN signature files exist (these don't exist yet for Python releases)
559+ local cosign_sig_url=" ${cpython_tgz_url} .sig"
560+ local cosign_cert_url=" ${cpython_tgz_url} .pem"
561+
562+ # Download COSIGN signature and certificate files with proper error handling
563+ echo " (*) Checking for cosign signature files..."
564+ if ! curl -sSL -f --fail-with-body -o " /tmp/python-src/${cpython_tgz_filename} .sig" " ${cosign_sig_url} " 2> /dev/null; then
565+ echo " (!) COSIGN signature file not available for Python ${VERSION} "
566+ echo " Signature URL: ${cosign_sig_url} "
567+ return 1
568+ fi
569+
570+ if ! curl -sSL -f --fail-with-body -o " /tmp/python-src/${cpython_tgz_filename} .pem" " ${cosign_cert_url} " 2> /dev/null; then
571+ echo " (!) COSIGN certificate file not available for Python ${VERSION} "
572+ echo " Certificate URL: ${cosign_cert_url} "
573+ return 1
574+ fi
575+
576+ # Perform COSIGN verification
577+ if cosign verify-blob \
578+ --certificate " /tmp/python-src/${cpython_tgz_filename} .pem" \
579+ --signature " /tmp/python-src/${cpython_tgz_filename} .sig" \
580+ --certificate-identity-regexp=" .*" \
581+ --certificate-oidc-issuer-regexp=" .*" \
582+ " /tmp/python-src/${cpython_tgz_filename} " ; then
583+ echo " (*) COSIGN signature verification successful"
584+ return 0
585+ else
586+ echo " (!) COSIGN signature verification failed"
587+ return 1
588+ fi
589+ }
590+
591+ # GPG verification for python versions < 3.14
592+ gpg_verification () {
593+ echo " (*) Using GPG signature verification..."
594+ if [[ ${VERSION_CODENAME} = " centos7" ]] || [[ ${VERSION_CODENAME} = " rhel7" ]]; then
595+ receive_gpg_keys_centos7 PYTHON_SOURCE_GPG_KEYS
596+ else
597+ receive_gpg_keys PYTHON_SOURCE_GPG_KEYS
598+ fi
599+ echo " Downloading ${cpython_tgz_filename} .asc..."
600+ curl -sSL -o " /tmp/python-src/${cpython_tgz_filename} .asc" " ${cpython_tgz_url} .asc"
601+ gpg --verify " ${cpython_tgz_filename} .asc"
602+ echo " (*) GPG signature verification successful"
603+ }
604+
481605
482606install_from_source () {
483607 VERSION=$1
@@ -507,15 +631,27 @@ install_from_source() {
507631 install_prev_vers_cpython " ${VERSION} "
508632 fi
509633 fi ;
510- # Verify signature
511- if [[ ${VERSION_CODENAME} = " centos7" ]] || [[ ${VERSION_CODENAME} = " rhel7" ]]; then
512- receive_gpg_keys_centos7 PYTHON_SOURCE_GPG_KEYS
634+
635+ # Discontinuation of PGP signatures for releases of Python 3.14 or future versions
636+ # CPython release artifacts are additionally signed with Sigstore starting with the Python 3.11.0
637+ local major_version=$( echo " $VERSION " | cut -d. -f1)
638+ local minor_version=$( echo " $VERSION " | cut -d. -f2)
639+ echo " (*) Detected Python version: ${major_version} .${minor_version} "
640+ if [ " $major_version " -eq 3 ] && [ " $minor_version " -ge 14 ]; then
641+ echo " (*) Python 3.14+ detected. Attempting cosign verification..."
642+ if cosign_verification " $VERSION " ; then
643+ echo " (*) COSIGN verification successful."
644+ else
645+ echo " (*) COSIGN verification failed or not available for Python ${VERSION} "
646+ echo " (*) WARNING: Installing Python ${VERSION} without signature verification"
647+ echo " (*) This is expected for newly released versions where cosign signatures are not yet available"
648+ echo " (*) Python 3.14+ discontinued PGP signatures in favor of cosign, but cosign signatures may take time to be published"
649+ fi
513650 else
514- receive_gpg_keys PYTHON_SOURCE_GPG_KEYS
651+ echo " (*) Python < 3.14 detected. Using GPG signature verification..."
652+ gpg_verification
653+ echo " (*) GPG verification successful."
515654 fi
516- echo " Downloading ${cpython_tgz_filename} .asc..."
517- curl -sSL -o " /tmp/python-src/${cpython_tgz_filename} .asc" " ${cpython_tgz_url} .asc"
518- gpg --verify " ${cpython_tgz_filename} .asc"
519655
520656 # Update min protocol for testing only - https://bugs.python.org/issue41561
521657 if [ -f /etc/pki/tls/openssl.cnf ]; then
0 commit comments