ruby/ruby · error · Gem::Security::Exception
trusted root certificate #{root.subject} checksum does not m
Error message
trusted root certificate #{root.subject} checksum does not match signing root certificate checksum What it means
check_trust found a trusted certificate file for the root's subject in the trust dir, but the digest (default SHA-256) of the saved certificate's public key differs from the digest of the root in the gem's chain. 'trusted root certificate ... checksum does not match signing root certificate checksum' means the stored trusted copy and the presented root share identity but not key material — the root was re-issued/re-generated under the same subject, so the old trust entry no longer corresponds.
Source
Thrown at lib/rubygems/security/policy.rb:173
path = Gem::Security.trust_dir.cert_path root
unless File.exist? path
message = "root cert #{root.subject} is not trusted".dup
message << " (root of signing cert #{chain.last.subject})" if
chain.length > 1
raise Gem::Security::Exception, message
end
save_cert = OpenSSL::X509::Certificate.new File.read path
save_dgst = digester.digest save_cert.public_key.public_to_pem
pkey_str = root.public_key.public_to_pem
cert_dgst = digester.digest pkey_str
raise Gem::Security::Exception,
"trusted root certificate #{root.subject} checksum " \
"does not match signing root certificate checksum" unless
save_dgst == cert_dgst
true
end
##
# Extracts the email or subject from +certificate+
def subject(certificate) # :nodoc:
certificate.extensions.each do |extension|
next unless extension.oid == "subjectAltName"
return extension.value
end
certificate.subject.to_sView on GitHub (pinned to 0e5b888e1c)
Solutions
- Update the trust entry: remove the stale certificate from the trust dir and add the current one — `gem cert --list`, `gem cert --remove <subject>`, then `gem cert --add new_root.pem`
- Get the new root cert from the gem author's authoritative source (verify out-of-band before trusting)
- If you manage the CA: avoid re-issuing under the same subject with new keys; prefer a new subject or keep the key
Example fix
# refresh stale trust entry gem cert --remove '/CN=old-root/...' gem cert --add new-gem-public_cert.pem gem install signed-gem -P HighSecurity
Defensive patterns
Strategy: fallback
Validate before calling
saved = OpenSSL::X509::Certificate.new(File.read(Gem::Security.trust_dir.cert_path(chain.first))) needs_refresh = Gem::Security.create_digest.digest(saved.public_key.public_to_pem) != Gem::Security.create_digest.digest(chain.first.public_key.public_to_pem)
Type guard
def trust_entry_current?(root) path = Gem::Security.trust_dir.cert_path(root) return false unless File.exist?(path) saved = OpenSSL::X509::Certificate.new(File.read(path)) saved.public_key.public_to_pem == root.public_key.public_to_pem end
Try / catch
begin
Gem::Package.new(gem_path, Gem::Security::Policies['HighSecurity']).verify
rescue Gem::Security::Exception => e
refresh_trust_entry(root_cert) if e.message.include?('checksum')
end Prevention
- When a CA/root is re-issued, refresh trust entries: gem cert --remove then --add
- Confirm new root certs with the author out-of-band before trusting
- As CA operator: never re-issue a subject with a different key; prefer a new subject
When it happens
Trigger: Author regenerated their root key+cert (same subject/email) after losing the old one; your trust dir still holds the previous certificate; a re-issued CA cert with identical subject but a new key. Check `Gem::Security.trust_dir.cert_path(root)` file exists, then digests diverge.
Common situations: Lost CA keys followed by `gem cert --build` re-creation; certificate renewal that changes the key; importing a different organization's cert with the same subject string.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- root cert #{root.subject} is not trusted
- missing root certificate
- root certificate #{root.subject} is not self-signed (issuer
- can not parse RUBY_DEBUG_LOG filename: %s\n
- RUBY_DEBUG_LOG=mem is not specified.
AI-assisted analysis of ruby/ruby@0e5b888e1c (2026-08-21).
Data as JSON: /api/errors/5aec0277d2eae76b.
Report an issue: GitHub.