Location>code7788 >text

Front-end RSA key generation and encryption/decryption - usage related

Popularity:440 ℃/2024-08-03 14:27:20

Reprinted from Jane's Books.Original addressThis article describes the API on RSA.


crypto API supports commonly used rsa, aes encryption and decryption, this side introduces the application of rsa.

Browser compatibility

Requires chrome version 37, ie 11, safari 11 to support the full API while basic encryption and decryption is fine in safari 7.

Generate public and private keys

(algorithm, extractable, keyUsages), among others:
1.algorithmParameters are filled in according to different algorithms, rsa needs to be filled in withRsaHashedKeyGenParamsThe object contains there:

  • nameOptionalRSASSA-PKCS1-v1_5, RSA-PSS, or RSA-OAEPThis side, if used for encryption and decryption is not supported by oldRSAES-PKCS1-v1_5of (support).RSASSA-PKCS1-v1_5For signatures

  • modulusLengthThis parameter most affects the performance, for example, 1024 is much faster than 2048, NIST recommends that the current RSA secret key security strength is 2048 bits, if you need to work after 2030, use 3072-bit secret key.

  • publicExponent, generally direct [0x01, 0x00, 0x01].

  • hashSummary method, optionalSHA-256SHA-384SHA-512I'm allowed to do that.SHA-1But it's not recommended because of its security.

2.extractableGenerally true, indicating whether or not to allow exporting the key as text.

3.keyUsagesis an array of optionalencryptdecryptsignet al. (and other authors)

(
    {
        name: "RSA-OAEP",
        modulusLength: 2048,
        publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
        hash: {
            name: "SHA-512" // This way, if the back-end uses public key encryption, be careful to align it with the front-end
        }, }
    },
    true.
    ["encrypt", "decrypt"] // must be ["encrypt", "decrypt"] or ["wrapKey", "unwrapKey"]
)

The result of the function returns a promise object, if it is symmetric encryption will get a keyCryptoKeytype, this side of rsa will get a key pairCryptoKeyPairIt has 2CryptoKeyMembership.privateKeycap (a poem)publicKeyIf we export the key as text or encrypt or decrypt it, it will be through these 2 member objects.

Exporting public and private keys

(format, key), among others:
1.formatselectablerawpkcs8spkijwkOn our side, when exporting the public key, we select thespkiPrivate key selectionpkcs8

2.keyIt's up there.CryptoKeyPair(used form a nominal expression)privateKeyorpublicKey
The function returns a promise object, the result is an ArrayBuffer, which is converted to pem style over here.

// Exporting Private Keys
 (
    "pkcs8", // For the public key, fill in this fieldspki
     // The public key side ispublicKey
).then(function(keydata2) {
    let privateKey = RSA2text(keydata1, 1) // private keypem
}).catch(function(err) {
    (err)
})
// pemformatted text
function RSA2text(buffer, isPrivate = 0) {
    let binary = ''
    const bytes = new Uint8Array(buffer)
    const len =
    for (let i = 0; i < len; i++) {
        binary += (bytes[i])
    }
    const base64 = (binary)
    let text = "-----BEGIN " + (isPrivate ? "PRIVATE" : "PUBLIC") + " KEY-----\n" // here are-----BEGINcap (a poem)-----It's fixed.
    text += (/[^\x00-\xff]/g, "$&\x01").replace(/.{64}\x01?/g, "$&\n") // interlocutorybase64encodings
    text += "\n-----END " + (isPrivate ? "PRIVATE" : "PUBLIC") + " KEY-----" // here are-----ENDcap (a poem)-----It's fixed.
    return text
}

Importing public and private keys

(
format,
keyData,
algorithm,
extractable,
keyUsages
)
, among others:
1.formatselectablerawpkcs8spkijwkThis corresponds to the choices we made when generating our public key.spkiPrivate key selectionpkcs8

2.keyDatanamelyObtained ArrayBuffer, because here when we generally only pem text, so also need to do the conversion to ArrayBuffer.

3.algorithmOn this side we are rsa and need to fill in aRsaHashedImportParamsobject, this side corresponds to therequiredRsaHashedKeyGenParamsObjects that contain:

  • nameAll remain the same as before.
  • hash

4.extractablesame(used form a nominal expression)

5.keyUsagessame
function returns a promise object, resulting in aCryptoKey

// Import the public key
const pub = "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo5NwYVVSg6rmAIKoxvCI
4Rn7FYh0mOFrnr0q2+r99/ZGuYCj5b6FQ8BwaaU8XpRn/y3W7W2bCggNRwllWQ2r
dHIM+6vN2Yi/QYntKqbcRNlK1s02G2lw9pERaWi15+5P8+AFR8IHANm/Dd/19OlM
5FZ9hh+qG7FXFhV2i4r62pUZxhk6ykItOT16IH5poK9eEDhqsXZ+3UW6cGlxANgO
jHJEnZpNCI5tS/4kFhLogHvEd88MoapljL6cZXk3ZafvxgUwxI6BZIhlw0adh2sj
bByIHitjRxqKMDH7uSdV9zf8t5Wa0bZFcUpcb5Jx2QBWIlO1qP+Q4LLMbNvEHeBC
4wIDAQAB
-----END PUBLIC KEY-----"

const pemHeader = "-----BEGIN PUBLIC KEY-----" // The header and footer identifiers inside the previous RSA2text function, this one is for the public key
const pemFooter = "-----END PUBLIC KEY-----"
const pemContents = (, - ) // Remove pem headers and footers.
// base64 decode
const binaryDer = (pemContents)
// convert to ArrayBuffer binary string
const binary = str2ab(binaryDer)
(
    "spki", // this side is pkcs8 if the key is private
    binary ,
    {
        name: "RSA-OAEP", hash: "SHA-512" // keep the same name.
        hash: "SHA-512" // Keep it consistent.
    }, { name: "RSA-OAEP", hash: "SHA-512" // consistent
    true.
    ["encrypt"] // The public key is used for encryption, the private key is decrypt.
)

function str2ab(str) {
    const buf = new ArrayBuffer()
    const bufView = new Uint8Array(buf)
    for (let i = 0, strLen = ; i < strLen; i++) {
        bufView[i] = (i)
    }
    return buf
}

encrypt and decrypt

encrypted(algorithm, key, data), among others:
1.algorithmThe encryption and decryption only supports RSA-OAEP but not RSAES-PKCS1-v1_5.

2.keyi.e., the public key'sCryptoKeyboyfriend

3.dataanBufferSourceobject, which cannot be directly the string to be encrypted.
The result is an ArrayBuffer, which can be output as a base64 string using ((... .new Uint8Array(e))) to output as a base64 string

const enc = new TextEncoder()
const data = ("sucks") // This side converts the encrypted string to a utf-8 Uint8Array.
(
    {
        name: "RSA-OAEP"
    }, publicKey, // Generate or import a key.
    publicKey, // The CryptoKey object generated or imported.
    data
)

declassification(algorithm, key, data)If it is a base64 string such as encrypted from the back-end, it needs to be converted to Uint8Array.

function base64ToUint8Array(base64String) {
    const padding = '='.repeat((4 -  % 4) % 4)
    const base64 = (base64String + padding).replace(/\-/g, '+').replace(/_/g, '/')

    const rawData = (base64)
    const outputArray = new Uint8Array()

    for (let i = 0; i < ; ++i) {
        outputArray[i] = (i)
    }
    return outputArray
}

The return value is the same as the encryption