在 GO 中使用 RSA-SHA 进行签名和解码

2024-01-12

我正在尝试签署一个字符串,然后用公钥验证它。我的验证结果为空。我究竟做错了什么?

    package main

import (
    "crypto"
    "crypto/rand"
    "crypto/rsa"
    "crypto/sha256"
    "crypto/x509"
    "encoding/base64"
    "encoding/pem"
    "errors"
    "fmt"
    "io/ioutil"
)

func main() {
    signer, err := loadPrivateKey("private.pem");
    if err != nil {
        fmt.Errorf("signer is damaged: %v", err)
    }

    toSign := "date: Thu, 05 Jan 2012 21:31:40 GMT";

    signed, err := signer.Sign([]byte(toSign))
    if err != nil {
        fmt.Errorf("could not sign request: %v", err)
    }
    sig := base64.StdEncoding.EncodeToString(signed)
    fmt.Printf("Encoded: %v\n", sig)


    parser, perr := loadPublicKey("public.pem");
    if perr != nil {
        fmt.Errorf("could not sign request: %v", err)
    }
    unsigned, err := parser.Unsign(signed);
     if err != nil {
        fmt.Errorf("could not sign request: %v", err)
    }

    fmt.Printf("Decrypted: %v\n", base64.StdEncoding.EncodeToString(unsigned))    
}


// loadPrivateKey loads an parses a PEM encoded private key file.
func loadPublicKey(path string) (Unsigner, error) {
        data, err := ioutil.ReadFile(path)

        if err != nil {
                return nil, err
        }
        return parsePublicKey(data)
}

// parsePublicKey parses a PEM encoded private key.
func parsePublicKey(pemBytes []byte) (Unsigner, error) {
        block, _ := pem.Decode(pemBytes)
        if block == nil {
                return nil, errors.New("ssh: no key found")
        }

        var rawkey interface{}
        switch block.Type {
        case "PUBLIC KEY":
                rsa, err := x509.ParsePKIXPublicKey(block.Bytes)
                if err != nil {
                        return nil, err
                }
                rawkey = rsa
        default:
                return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
        }

        return newUnsignerFromKey(rawkey)
}


// loadPrivateKey loads an parses a PEM encoded private key file.
func loadPrivateKey(path string) (Signer, error) {
        data, err := ioutil.ReadFile(path)
        if err != nil {
                return nil, err
        }
        return parsePrivateKey(data)
}

// parsePublicKey parses a PEM encoded private key.
func parsePrivateKey(pemBytes []byte) (Signer, error) {
        block, _ := pem.Decode(pemBytes)
        if block == nil {
                return nil, errors.New("ssh: no key found")
        }

        var rawkey interface{}
        switch block.Type {
        case "RSA PRIVATE KEY":
                rsa, err := x509.ParsePKCS1PrivateKey(block.Bytes)
                if err != nil {
                        return nil, err
                }
                rawkey = rsa
        default:
                return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
        }
        return newSignerFromKey(rawkey)
}

// A Signer is can create signatures that verify against a public key.
type Signer interface {
        // Sign returns raw signature for the given data. This method
        // will apply the hash specified for the keytype to the data.
        Sign(data []byte) ([]byte, error)
}

// A Signer is can create signatures that verify against a public key.
type Unsigner interface {
        // Sign returns raw signature for the given data. This method
        // will apply the hash specified for the keytype to the data.
        Unsign(data []byte) ([]byte, error)
}

func newSignerFromKey(k interface{}) (Signer, error) {
        var sshKey Signer
        switch t := k.(type) {
        case *rsa.PrivateKey:
                sshKey = &rsaPrivateKey{t}
        default: 
                return nil, fmt.Errorf("ssh: unsupported key type %T", k)
        }
        return sshKey, nil
}

func newUnsignerFromKey(k interface{}) (Unsigner, error) {
        var sshKey Unsigner
        switch t := k.(type) {
        case *rsa.PublicKey:
                sshKey = &rsaPublicKey{t}
        default:
                return nil, fmt.Errorf("ssh: unsupported key type %T", k)
        }
        return sshKey, nil
}

type rsaPublicKey struct {
    *rsa.PublicKey
}

type rsaPrivateKey struct {
        *rsa.PrivateKey
}

// Sign signs data with rsa-sha256
func (r *rsaPrivateKey) Sign(data []byte) ([]byte, error) {
        h := sha256.New()
        h.Write(data)
        d := h.Sum(nil)
        return rsa.SignPKCS1v15(rand.Reader, r.PrivateKey, crypto.SHA256, d)
}

// Unsign encrypts data with rsa-sha256
func (r *rsaPublicKey) Unsign(message []byte) ([]byte, error) {  
        return rsa.EncryptPKCS1v15(rand.Reader, r.PublicKey, message)        
}

private.pem 看起来像这样:

-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQDCFENGw33yGihy92pDjZQhl0C36rPJj+CvfSC8+q28hxA161QF
NUd13wuCTUcq0Qd2qsBe/2hFyc2DCJJg0h1L78+6Z4UMR7EOcpfdUE9Hf3m/hs+F
UR45uBJeDK1HSFHD8bHKD6kv8FPGfJTotc+2xjJwoYi+1hqp1fIekaxsyQIDAQAB
AoGBAJR8ZkCUvx5kzv+utdl7T5MnordT1TvoXXJGXK7ZZ+UuvMNUCdN2QPc4sBiA
QWvLw1cSKt5DsKZ8UETpYPy8pPYnnDEz2dDYiaew9+xEpubyeW2oH4Zx71wqBtOK
kqwrXa/pzdpiucRRjk6vE6YY7EBBs/g7uanVpGibOVAEsqH1AkEA7DkjVH28WDUg
f1nqvfn2Kj6CT7nIcE3jGJsZZ7zlZmBmHFDONMLUrXR/Zm3pR5m0tCmBqa5RK95u
412jt1dPIwJBANJT3v8pnkth48bQo/fKel6uEYyboRtA5/uHuHkZ6FQF7OUkGogc
mSJluOdc5t6hI1VsLn0QZEjQZMEOWr+wKSMCQQCC4kXJEsHAve77oP6HtG/IiEn7
kpyUXRNvFsDE0czpJJBvL/aRFUJxuRK91jhjC68sA7NsKMGg5OXb5I5Jj36xAkEA
gIT7aFOYBFwGgQAQkWNKLvySgKbAZRTeLBacpHMuQdl1DfdntvAyqpAZ0lY0RKmW
G6aFKaqQfOXKCyWoUiVknQJAXrlgySFci/2ueKlIE1QqIiLSZ8V8OlpFLRnb1pzI
7U1yQXnTAEFYM560yJlzUpOb1V4cScGd365tiSMvxLOvTA==
-----END RSA PRIVATE KEY-----

和 public.pem:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCFENGw33yGihy92pDjZQhl0C3
6rPJj+CvfSC8+q28hxA161QFNUd13wuCTUcq0Qd2qsBe/2hFyc2DCJJg0h1L78+6
Z4UMR7EOcpfdUE9Hf3m/hs+FUR45uBJeDK1HSFHD8bHKD6kv8FPGfJTotc+2xjJw
oYi+1hqp1fIekaxsyQIDAQAB
-----END PUBLIC KEY-----

Thanks.


你的代码中的问题是Unsign尝试对签名进行编码,而不是使用它来验证原始消息。

需要对接口进行更改Unsign:

// Unsign verifies the message using a rsa-sha256 signature
func (r *rsaPublicKey) Unsign(message []byte, sig []byte) error {
    h := sha256.New()
    h.Write(message)
    d := h.Sum(nil)
    return rsa.VerifyPKCS1v15(r.PublicKey, crypto.SHA256, d, sig)
}

这是验证的游乐场示例:http://play.golang.org/p/bzpD7Pa9mr http://play.golang.org/p/bzpD7Pa9mr

还进行了一些修改以避免 ioutils。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 GO 中使用 RSA-SHA 进行签名和解码 的相关文章

随机推荐

  • SQLAlchemy 声明式:没有任何主键的表?

    如何使用ORM声明类创建没有主键的表 如果我没有制作任何专栏 它就无法启动primary key True SQLAlchemy 核心不会抱怨缺少主键 因此可以使用以下命令创建这样的表Table 但是ORM在设计上需要一种方法来识别对象对应
  • setColorFilter 不起作用

    我正在尝试在图像视图上实现一个简单的滤色器 将黑色图像变成白色图像 为了实现这一目标 我执行以下操作 weatherImg setColorFilter Color BLACK PorterDuff Mode MULTIPLY weathe
  • 异常类 - What() 函数

    我目前正在开发自己的异常类 该类继承自std exception 我不确定我是否应该自己做what 或者只是打电话std exception message 在我的类构造函数中 这是我当前的代码 FilterException Filter
  • 如何设置字体大小或标签大小以适合所有设备

    如何设置 kivy 字体大小或标签大小 使其适合所有手机设备屏幕 适合的方式是不与边界 矩形 甚至屏幕重叠 我知道 Kivy 中的按钮和其他一些小部件有size hint This size hint没有给出想要的结果 另外 设置font
  • 如何导入npgsql模块?

    我需要从 PowerShell 脚本中连接到 PostgreSQL 数据库 但是如何在没有 VisualStudio 的情况下安装 npgsql 呢 没有金块 所以我尝试使用最新的 MSI 文件在 GAC 中安装驱动程序 Npgsql 3
  • 尝试在 VS Code 中将 emmet 与 React 应用程序一起使用

    我正在使用 Visual Studio Code 并创建一个 React 应用程序 我知道 Emmet 附带了 Vsc 但它不适用于我的 React 应用程序 我尝试将以下代码放入设置中 emmet includeLanguages jav
  • 图像Python3的中值滤波器

    I wanted to implement a radial median filter I have the following picture size Nx Ny 我想导出每个像素的半径 对于每个半径计算中值并将其放入一个新矩阵中以代
  • 如何读取 ASP.NET 原始 URL 的查询字符串参数?

    我有一个变量 string rawURL HttpContext Current Request RawUrl 如何读取此 url 的查询字符串参数 这可能就是你想要的 Uri theRealURL new Uri HttpContext
  • JavaScript 数组与 JSON 响应的比较

    我正在处理这个项目 我需要从学校的时间表中获取所有空房间 我可以从 JSON 响应中获取数据 JSON 响应如下所示 status success reservations id 19598 subject subjectName modi
  • Linux cli 工具将 SQL Server 架构转储到文本文件

    您知道能够将 SQL Server 架构导出到文本文件的可靠命令行工具吗 您可以使用 mssql scripter 来完成此操作 下载通过 pip install mssql scripter 您要使用的命令类似于 mssql script
  • ios5 ARC 从 ARC 中排除文件的编译器标志是什么?

    谁能帮我记住告诉 XCode 对某些文件不使用 ARC 的标志是什么 我的项目中有几个文件被标记为这样 直到我添加了另一个文件并决定将该文件转换为 ARC 听起来很容易 对吧 我期望能够简单地检查我想要的文件并让 XCode 发挥它的魔力
  • Jenkins 内容安全策略

    我对詹金斯内容安全策略感到困惑 我知道这些网站 配置内容安全策略 https wiki jenkins ci org display JENKINS Configuring Content Security Policy 内容安全策略参考
  • 区分 VMware 网络适配器和物理网络适配器 - 或 - 检测虚拟网络适配器

    我必须使用任何 Windows API 来区分真实地址和虚拟机地址 我在用着GetAdaptersAddresses用于填充本地计算机的 IP 地址列表的 API 我只需要提取除与 VMware 网络适配器关联的地址和其他地址 自动配置和隧
  • 从 ExecutionEngine 调用 C/C++ 函数

    我正在学习 llvm 想要对我的想法进行概念验证 基本上 我想分割我的编译器和运行时 编译器将给出一个 bc 运行时将通过 ParseBitcodeFile 加载它并使用 ExecutionEngine 来运行它 这部分正在发挥作用 现在
  • 通过链接克服云代码解析限制 1000?

    我有以下函数 我用它来确定用户在记分牌中的排名 Parse Cloud define getUserGlobalRank function request response var usernameString request params
  • 如何从网格中检查复选框获取详细信息?

    我有EditorGridPanel 网格的ColumnModel包括TextField ComboBox和CheckBox 编辑 TextField 或 ComboBox 后 将触发 afteredit 事件 其中包含有关已编辑字段的详细信
  • 使用 es6 进行 chrome 调试

    我正在尝试在我的项目中使用 Ecmascript 2015 但我发现很难在特定位置添加断点 我认为设置断点是合乎逻辑的位置 我在 chrome 中将 enable javascript harmony 标志设置为 true 如果有帮助 但我
  • 如何使用 MiniTest 测试记录器消息?

    我有一个应用程序 我想测试我是否正确 来自我的记录器的消息 一个简短的示例 您可以在 log4r 和 logger 之间切换 gem minitest require minitest autorun require log4r requi
  • 共享首选项中的数据缓存

    我的应用程序中有 2 个进程 从一个进程我将数据保存到SharedPreferences 从第二个过程 检索 当我检索数据时 我收到SharedPreferences使用旧数据 我检查 xml 文件 发现当前文件中的数据和收到的数据不同 看
  • 在 GO 中使用 RSA-SHA 进行签名和解码

    我正在尝试签署一个字符串 然后用公钥验证它 我的验证结果为空 我究竟做错了什么 package main import crypto crypto rand crypto rsa crypto sha256 crypto x509 enco