如何将RSA密钥对(字符串)转换为加密密钥以签名数据

发布于 2025-01-30 06:12:21 字数 2125 浏览 2 评论 0原文

我使用此C#方法作为字符串将私钥发送到我的JavaScript:

public static string SignData(string certPath,string certPass)
{
       X509Certificate2 keyStore = new X509Certificate2(AppDomain.CurrentDomain.BaseDirectory + "Certifikatat\\" + certPath, certPass, X509KeyStorageFlags.Exportable);
       RSA privateKey = keyStore.GetRSAPrivateKey();

       TextWriter textWriter = new StringWriter();
       var eky = DotNetUtilities.GetRsaKeyPair(privateKey);
       PemWriter pemWriter = new PemWriter(textWriter);
       pemWriter.WriteObject(eky);
       pemWriter.Writer.Flush();
       return pemWriter.Writer.ToString();
}

现在我需要将字符串转换为cryptokey,以便用于签署某些数据。 我尝试了以下代码:

window.crypto.subtle.importKey(
        "pkcs8",
        pemToArrayBuffer(pk),
        {
            name: "RSASSA-PKCS1-v1_5",
            hash: { name: "SHA-256" },
        },
        false,
        ["sign"]
    )
    .then(function (publicKey) {
        //returns a publicKey (or privateKey if you are importing a private key)
        console.log(publicKey);
    })
    .catch(function (err) {
        console.error(err);
    });

}
function removeLines(str) {
    str = str.replace("\r", "");
    return str.replace("\n", "");
}

function base64ToArrayBuffer(b64) {
    var byteString = btoa(b64);
    var byteArray = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) {
         byteArray[i] = byteString.charCodeAt(i);
    }

    return byteArray;
}

function pemToArrayBuffer(pem) {
    var b64Lines = removeLines(pem);
    var b64Prefix = b64Lines.replace('-----BEGIN RSA PRIVATE KEY-----', '');
    var b64Final = b64Prefix.replace('----- END RSA PRIVATE KEY-----', '');

    return base64ToArrayBuffer(b64Final);
}

pk是RSA对密钥,现在我需要将其转换为:

var signature = window.crypto.subtle.sign("RSA_PKCS1_SHA256", pks, bytes);

pks应该是cryptokey 由pk字符串生成。

I used this C# method to send a private key to my javascript as a string:

public static string SignData(string certPath,string certPass)
{
       X509Certificate2 keyStore = new X509Certificate2(AppDomain.CurrentDomain.BaseDirectory + "Certifikatat\\" + certPath, certPass, X509KeyStorageFlags.Exportable);
       RSA privateKey = keyStore.GetRSAPrivateKey();

       TextWriter textWriter = new StringWriter();
       var eky = DotNetUtilities.GetRsaKeyPair(privateKey);
       PemWriter pemWriter = new PemWriter(textWriter);
       pemWriter.WriteObject(eky);
       pemWriter.Writer.Flush();
       return pemWriter.Writer.ToString();
}

Now I need to convert the string to a CryptoKey in order to be used for signing some data.
I tried the following code:

window.crypto.subtle.importKey(
        "pkcs8",
        pemToArrayBuffer(pk),
        {
            name: "RSASSA-PKCS1-v1_5",
            hash: { name: "SHA-256" },
        },
        false,
        ["sign"]
    )
    .then(function (publicKey) {
        //returns a publicKey (or privateKey if you are importing a private key)
        console.log(publicKey);
    })
    .catch(function (err) {
        console.error(err);
    });

}
function removeLines(str) {
    str = str.replace("\r", "");
    return str.replace("\n", "");
}

function base64ToArrayBuffer(b64) {
    var byteString = btoa(b64);
    var byteArray = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) {
         byteArray[i] = byteString.charCodeAt(i);
    }

    return byteArray;
}

function pemToArrayBuffer(pem) {
    var b64Lines = removeLines(pem);
    var b64Prefix = b64Lines.replace('-----BEGIN RSA PRIVATE KEY-----', '');
    var b64Final = b64Prefix.replace('----- END RSA PRIVATE KEY-----', '');

    return base64ToArrayBuffer(b64Final);
}

pk is the rsa pair key and now i need to convert it in order to be used by:

var signature = window.crypto.subtle.sign("RSA_PKCS1_SHA256", pks, bytes);

pks should be the CryptoKey generated by the pk string.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

抱着落日 2025-02-06 06:12:21

C#代码不会以PKCS#8格式导出密钥,而是以PKCS#1格式导出密钥。由于WebCrypto API仅支持PKCS#8格式,因此必须更改:

...
Org.BouncyCastle.OpenSsl.Pkcs8Generator pkcs8Gen = new Org.BouncyCastle.OpenSsl.Pkcs8Generator(eky.Private);
Org.BouncyCastle.Utilities.IO.Pem.PemObject pkcs8 = pkcs8Gen.Generate();
Org.BouncyCastle.OpenSsl.PemWriter pemWriter = new Org.BouncyCastle.OpenSsl.PemWriter(new StringWriter());
pemWriter.WriteObject(pkcs8);
...

中间的两行要照顾转换为PKCS#8格式键。


此外,在base64toArrayBuffer()中的JavaScript代码中,btoa()函数必须替换为atob()函数。另外,在pemtoarraybuffer()中,必须删除PKCS#8标头和页脚,即------ /code>和-----结束私钥-----

通过这些更改,在C#代码中,PKCS#8密钥被导出,在JavaScript代码中,PKCS#8密钥将导入到cryptokey中。

完整的JavaScript代码(包括签名):

var pkcs8Pem = `-----BEGIN PRIVATE KEY-----
MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEA2gdsVIRmg5IH0rG3
u3w+gHCZq5o4OMQIeomC1NTeHgxbkrfznv7TgWVzrHpr3HHK8IpLlG04/aBo6U5W
2umHQQIDAQABAkEAu7wulGvZFat1Xv+19BMcgl3yhCdsB70Mi+7CH98XTwjACk4T
+IYv4N53j16gce7U5fJxmGkdq83+xAyeyw8U0QIhAPIMhbtXlRS7XpkB66l5DvN1
XrKRWeB3RtvcUSf30RyFAiEA5ph7eWXbXWpIhdWMoe50yffF7pW+C5z07tzAIH6D
Ko0CIQCyveSTr917bdIxk2V/xNHxnx7LJuMEC5DcExorNanKMQIgUxHRQU1hNgjI
sXXZoKgfaHaa1jUZbmOPlNDvYYVRyS0CIB9ZZee2zubyRla4qN8PQxCJb7DiICmH
7nWP7CIvcQwB
-----END PRIVATE KEY-----`; // For simplicity, a 512 bit demo key. In practice, keys >= 2048 bits must be used for security reasons!

// Import PKCS#8 key into CryptoKey
window.crypto.subtle.importKey(
    "pkcs8",
    pemToArrayBuffer(pkcs8Pem),
    {
        name: "RSASSA-PKCS1-v1_5",
        hash: { name: "SHA-256" },
    },
    false,
    ["sign"]
)
.then(function (privateKey) {
    console.log(privateKey);
    // Sign: RSA with SHA256 and PKCS#1 v1.5 padding
    window.crypto.subtle.sign(
        {
            name: "RSASSA-PKCS1-v1_5",
        },
        privateKey, 
        new TextEncoder().encode('The quick brown fox jumps over the lazy dog') 
    )
    .then(function(signature){
        console.log(ab2b64(signature)); // jIPK2Jftokn+yeuiMQYdWF2vyZF3Jn4+cbuKP84HzGZjv033ry4cGUXSprtC6yXwQiKLWR/BjNqC2Syq6ERnDA==
    })
    .catch(function(err){
        console.error(err);
    });
})
.catch(function (err) {
    console.error(err);
});

function ab2b64(arrayBuffer) {
    return window.btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));
}

function removeLines(str) {
    str = str.replace("\r", "");
    return str.replace("\n", "");
}

function base64ToArrayBuffer(b64) {
    //var byteString = btoa(b64);
    var byteString = atob(b64); // Fix
    var byteArray = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) {
         byteArray[i] = byteString.charCodeAt(i);
    }
    return byteArray;
}

function pemToArrayBuffer(pem) {
    var b64Lines = removeLines(pem);
    //var b64Prefix = b64Lines.replace('-----BEGIN RSA PRIVATE KEY-----', '');
    //var b64Final = b64Prefix.replace('----- END RSA PRIVATE KEY-----', '');
    var b64Prefix = b64Lines.replace('-----BEGIN PRIVATE KEY-----', ''); // Fix
    var b64Final = b64Prefix.replace('-----END PRIVATE KEY-----', ''); // fix
    return base64ToArrayBuffer(b64Final);
}

The C# code does not export the key in PKCS#8 format, but in PKCS#1 format. Since the WebCrypto API only supports the PKCS#8 format, this must be changed:

...
Org.BouncyCastle.OpenSsl.Pkcs8Generator pkcs8Gen = new Org.BouncyCastle.OpenSsl.Pkcs8Generator(eky.Private);
Org.BouncyCastle.Utilities.IO.Pem.PemObject pkcs8 = pkcs8Gen.Generate();
Org.BouncyCastle.OpenSsl.PemWriter pemWriter = new Org.BouncyCastle.OpenSsl.PemWriter(new StringWriter());
pemWriter.WriteObject(pkcs8);
...

The two lines in the middle take care of the conversion to a PKCS#8 formatted key.


Additionally, in the JavaScript code in base64ToArrayBuffer(), the btoa() function must be replaced with the atob() function. Also, in pemToArrayBuffer(), instead of the PKCS#1, the PKCS#8 headers and footers must be removed, i.e. -----BEGIN PRIVATE KEY----- and -----END PRIVATE KEY-----.

With these changes, in the C# code, a PKCS#8 key is exported and in the JavaScript code, a PKCS#8 key is imported into a CryptoKey.

Full JavaScript code (including signing):

var pkcs8Pem = `-----BEGIN PRIVATE KEY-----
MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEA2gdsVIRmg5IH0rG3
u3w+gHCZq5o4OMQIeomC1NTeHgxbkrfznv7TgWVzrHpr3HHK8IpLlG04/aBo6U5W
2umHQQIDAQABAkEAu7wulGvZFat1Xv+19BMcgl3yhCdsB70Mi+7CH98XTwjACk4T
+IYv4N53j16gce7U5fJxmGkdq83+xAyeyw8U0QIhAPIMhbtXlRS7XpkB66l5DvN1
XrKRWeB3RtvcUSf30RyFAiEA5ph7eWXbXWpIhdWMoe50yffF7pW+C5z07tzAIH6D
Ko0CIQCyveSTr917bdIxk2V/xNHxnx7LJuMEC5DcExorNanKMQIgUxHRQU1hNgjI
sXXZoKgfaHaa1jUZbmOPlNDvYYVRyS0CIB9ZZee2zubyRla4qN8PQxCJb7DiICmH
7nWP7CIvcQwB
-----END PRIVATE KEY-----`; // For simplicity, a 512 bit demo key. In practice, keys >= 2048 bits must be used for security reasons!

// Import PKCS#8 key into CryptoKey
window.crypto.subtle.importKey(
    "pkcs8",
    pemToArrayBuffer(pkcs8Pem),
    {
        name: "RSASSA-PKCS1-v1_5",
        hash: { name: "SHA-256" },
    },
    false,
    ["sign"]
)
.then(function (privateKey) {
    console.log(privateKey);
    // Sign: RSA with SHA256 and PKCS#1 v1.5 padding
    window.crypto.subtle.sign(
        {
            name: "RSASSA-PKCS1-v1_5",
        },
        privateKey, 
        new TextEncoder().encode('The quick brown fox jumps over the lazy dog') 
    )
    .then(function(signature){
        console.log(ab2b64(signature)); // jIPK2Jftokn+yeuiMQYdWF2vyZF3Jn4+cbuKP84HzGZjv033ry4cGUXSprtC6yXwQiKLWR/BjNqC2Syq6ERnDA==
    })
    .catch(function(err){
        console.error(err);
    });
})
.catch(function (err) {
    console.error(err);
});

function ab2b64(arrayBuffer) {
    return window.btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));
}

function removeLines(str) {
    str = str.replace("\r", "");
    return str.replace("\n", "");
}

function base64ToArrayBuffer(b64) {
    //var byteString = btoa(b64);
    var byteString = atob(b64); // Fix
    var byteArray = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) {
         byteArray[i] = byteString.charCodeAt(i);
    }
    return byteArray;
}

function pemToArrayBuffer(pem) {
    var b64Lines = removeLines(pem);
    //var b64Prefix = b64Lines.replace('-----BEGIN RSA PRIVATE KEY-----', '');
    //var b64Final = b64Prefix.replace('----- END RSA PRIVATE KEY-----', '');
    var b64Prefix = b64Lines.replace('-----BEGIN PRIVATE KEY-----', ''); // Fix
    var b64Final = b64Prefix.replace('-----END PRIVATE KEY-----', ''); // fix
    return base64ToArrayBuffer(b64Final);
}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文