{"record":{"id":"879c7150306c06e1","repo":"ruby/ruby","slug":"incorrect-signing-key-for-re-signing-expired-cer","errorCode":null,"errorMessage":"incorrect signing key for re-signing #{expired_certificate.subject}","messagePattern":"incorrect signing key for re-signing #(.+?)","errorType":"exception","errorClass":"Gem::Security::Exception","httpStatus":null,"severity":"error","filePath":"lib/rubygems/security.rb","lineNumber":509,"sourceCode":"\n    cn, dcs = email_address.split \"@\"\n\n    dcs = dcs.split \".\"\n\n    OpenSSL::X509::Name.new([\n      [\"CN\", cn],\n      *dcs.map {|dc| [\"DC\", dc] },\n    ])\n  end\n\n  ##\n  # Signs +expired_certificate+ with +private_key+ if the keys match and the\n  # expired certificate was self-signed.\n  #--\n  # TODO increment serial\n\n  def self.re_sign(expired_certificate, private_key, age = ONE_YEAR, extensions = EXTENSIONS)\n    raise Gem::Security::Exception,\n          \"incorrect signing key for re-signing \" +\n          expired_certificate.subject.to_s unless\n      expired_certificate.check_private_key(private_key)\n\n    unless expired_certificate.subject.to_s ==\n           expired_certificate.issuer.to_s\n      subject = alt_name_or_x509_entry expired_certificate, :subject\n      issuer  = alt_name_or_x509_entry expired_certificate, :issuer\n\n      raise Gem::Security::Exception,\n            \"#{subject} is not self-signed, contact #{issuer} \" \\\n            \"to obtain a valid certificate\"\n    end\n\n    serial = expired_certificate.serial + 1\n\n    create_cert_self_signed(expired_certificate.subject, private_key, age,\n                            extensions, serial)","sourceCodeStart":491,"sourceCodeEnd":527,"githubUrl":"https://github.com/ruby/ruby/blob/0e5b888e1c355f3f728f2659f085820937dada48/lib/rubygems/security.rb#L491-L527","documentation":"Gem::Security.re_sign (reached automatically from Gem::Security::Signer#sign when your signing certificate expires during gem build) first calls expired_certificate.check_private_key(private_key); if the private key does not match the certificate's public key it refuses to re-sign. The message names the certificate subject so you can tell which pair is mismatched.","triggerScenarios":"gem build with an expired ~/.gem/gem-public_cert.pem while gem-private_key.pem belongs to a different key pair; regenerating the key (or cert) at a different time so the two files no longer match; copying only one half of a pair between machines.","commonSituations":"Multi-machine or CI signing where the key and cert were sourced separately; recovering after cert expiry with a newly built key; stale certs left in place while the key was rebuilt via gem cert --build.","solutions":["Rebuild a matching pair and reinstall the cert: gem cert --build you@example.com, then gem cert --add gem-public_cert.pem, keeping gem-private_key.pem and gem-public_cert.pem together","Before building, verify pairing yourself: OpenSSL::X509::Certificate.new(File.read(cert)).check_private_key(OpenSSL::PKey.read(File.read(key)))","Set :expiration_length_days in ~/.gemrc so certs are re-signed automatically while the correct key is still configured"],"exampleFix":"# before: expired cert + wrong key on disk\n$ gem build mygem.gemspec\n#=> incorrect signing key for re-signing /CN=me/DC=example/DC=com\n\n# after: rebuild the pair together\n$ gem cert --build me@example.com\n$ gem cert --add gem-public_cert.pem\n$ gem build mygem.gemspec","handlingStrategy":"validation","validationCode":"cert = OpenSSL::X509::Certificate.new(File.read(cert_path))\nkey  = OpenSSL::PKey.read(File.read(key_path))\nraise \"key does not match #{cert.subject}\" unless cert.check_private_key(key)\nwarn \"cert expires #{cert.not_after} — rebuild the pair soon\" if cert.not_after < Time.now + 30*24*3600","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Store and back up gem-private_key.pem and gem-public_cert.pem strictly as a pair","Add a pre-build check: cert.check_private_key(key) plus an expiry warning with enough lead time to re-issue","Set :expiration_length_days in ~/.gemrc so auto re-sign fires while your (correct) key is still configured"],"tags":["rubygems","gem-signing","certificates","keys","expiry"],"backgroundTag":"private-key-certificate-mismatch","analyzedSha":"0e5b888e1c355f3f728f2659f085820937dada48","analyzedAt":"2026-08-21T14:25:43.473Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}