Java版SHA256WithRSA签名转Ruby后报签名长度错误如何解决
RSA签名长度错误问题排查及解决方案
错误根因说明
你收到的错误 IAM Exception: IAM-1000:Signature length not correct: got 256 but was expecting 384 本质是RSA密钥长度不匹配导致:
RSA签名长度和密钥长度直接对应,2048位RSA私钥生成的签名固定为256字节,3072位RSA私钥生成的签名固定为384字节,说明你当前使用的私钥为2048位,而服务端期望使用3072位私钥生成签名。
代码对齐问题排查点
除了密钥长度问题,你的Ruby实现和Java示例还有几处逻辑差异,也可能导致签名校验失败:
1. Base64编码规则错误
Java示例使用标准Base64编码,而你使用了URL安全的Base64编码,两者的字符映射、末尾补等号的规则不同,会直接导致签名内容不匹配。
修复方案:将签名编码逻辑替换为:
signature_string = Base64.strict_encode64(signature)
2. 待签名字符串未做空白处理
Java的canonicalize方法中对参数的key和value都做了trim()去除首尾空白的处理,你的Ruby代码直接拼接原始值,若参数存在首尾空白会导致待签名内容和Java生成的不一致。
修复方案:调整字符串拼接逻辑:
sorted_keys.each do |key| value = to_encrypt[key] names += "#{key.strip};" canstr += "#{value.to_s.strip}\n" end
3. 私钥一致性校验
确认你Ruby代码中填写的私钥和Java示例使用的私钥完全一致:
- 检查私钥字符串是否完整,是否存在多余的换行、空格、字符遗漏
- 可通过代码输出密钥位数确认:
- Java侧添加日志:
System.out.println(resolvedPrivateKey.getEncoded().length * 8); - Ruby侧添加日志:
puts key.n.num_bits
两者输出需要一致,且为3072位才能生成符合服务端要求的384字节签名。
- Java侧添加日志:
4. 签名填充规则显式指定
Java的SHA256WithRSA默认使用PKCS#1 v1.5填充,Ruby的sign方法默认也是该填充规则,若以上排查都无问题,可显式指定填充规则避免异常:
signature = key.sign('SHA256', final_arr[1], padding: OpenSSL::PKey::RSA::PKCS1_PADDING)
内容的提问来源于stack exchange,提问作者OndrejK
相关产品推荐
相关产品推荐

