Location>code7788 >text

OSS Token Generation in Browser | Web Crypto API

Popularity:296 ℃/2024-10-06 20:04:56

When the author writes an article, he puts the images through a simple site he built himself/ Upload images to object storage services (OSS) in various clouds.

The images are then accessed via CDN to ensure that they have reliable access speed and quality.

In line with the principle of as simple as possible to reduce the dependence on the back-end, the upload token is generated locally () and set an expiration time, directly pasted in the browser, stored in LocalStorage, the expiration of the local re-generation of once on the line.

However, there are still 2 trouble spots when generating: ① Dependency on the environment ② The key is stored in a local file.

This iteration is to get rid of these 2 trouble spots!

Generation Principle

cirrus (cloud)

Refer to the documentation:token authentication generation

Simplified into JS code as follows

// Basic configuration
const operator = 'account'
const password = 'password'
const method = 'PUT' // The request method to use when uploading
const urlPrefix = 'bucketName/sourcePrefix' // The bucket name and public path prefix of the resource on OSS
const expire = (() / 1000) + 3600 // expiration time expires after 1 hour

// Calculate the token
const token = base64(hmacSha1(MD5(password), `${method}&${urlPrefix}&${expire}`))

// The request header for the final upload
const Authorization = `UPYUN ${operator}:${token}`)

Dependent algorithms

  • base64: encoding for converting data to ASCII strings
  • HMAC_SHA-1: Message authentication code based on the SHA-1 hash algorithm, used to verify the integrity and authenticity of the message
  • MD5: Hash function, used to generate a digital fingerprint of the data

Seven Bulls Cloud

Refer to the documentation:Upload VoucherURL-Safe Base64 Encoding

Simplified into JS code as follows

// Basic Configuration
const accessKey = 'ACCESS_KEY'
const secretKey = 'SECRET_KEY'
const bucket = 'BUCKET_NAME' // OSS Barrel name
const expires = (() / 1000) + 3600 // expiration date (of document) 1Expires in hours

const encodedFlags = base64ToUrlSafe(base64(({
  scope: bucket,
  deadline: expires,
})))
const encodedSign = base64ToUrlSafe(base64(hmacSha1(secretKey, encodedFlags)))

// Token used for final upload
const uploadToken = `${accessKey}:${encodedSign}:${encodedFlags}`

included among thesebase64ToUrlSafe Methods related to "URL-Safe Base64 Encoding"

URL-safe Base64 encoding is suitable for scenarios where the Base64 encoded result is passed as a URL. The basic process of this encoding method is to first encode the content as a string in Base64 format, and then examine that result string to remove the plus sign from the string.+replace with an underscore-and the slash/Replace with underline_

// The realization is as follows
function base64ToUrlSafe(v: string) {
  return (/\//g, '_').replace(/\+/g, '-')
}

The other dependency algorithms are basically the same as those of AnotherCloudhmacSha1 cap (a poem)base64

Implementation of encryption methods

Here is a simple implementation for the browser and the environment, respectively.

Front-end browser-side implementation

Both the base64 and HMAC_SHA-1 algorithms have ready-to-use implementations, and can be implemented using the browser-suppliedbtoa cap (a poem)Crypto API。

function base64(value: string) {
  return btoa(value)
}

HMAC_SHA-1

studyingMDN: Crypto API The first thing you can see when documenting The description.

It's not hard to see literally the API we need.

through (a gap)HMAC The key information we need can be found in the example of the

The key code is as follows

const encoder = new TextEncoder()
const encoded = (value)
const signature = await ('HMAC', key, encoded)

included among thesekey is the key we need and can be used with() Import Generation.

const encoder = new TextEncoder()
const key = await (
  'raw',
  (password), // password It's our key.
  { name: 'HMAC', hash: { name: 'SHA-1' } },
  false,
  ['sign'],
)

The final implementation of our method is as follows.

async function hmacSha1(key: string, value: string) {
  const encoder = new TextEncoder()

  const cryptoKey = await (
    'raw',
    (key),
    { name: 'HMAC', hash: { name: 'SHA-1' } },
    false,
    ['sign'],
  )

  const data = (value)
  const hashBuffer = await ('HMAC', cryptoKey, data)

  return arrayBufferToBase64(hashBuffer) // come (or go) back base64 Formatting results
}

function arrayBufferToBase64(buffer: ArrayBuffer) {
  const uint8Array = new Uint8Array(buffer)
  const base64String = (...uint8Array)
  return btoa(base64String)
}

MD5

MD5 can be used with open source librariesspark-md5

import SparkMD5 from 'spark-md5'

export function MD5(str: string): string {
  return (str)
}

realization

environment, you can directly use the built-innode:crypto The various encryption algorithms provided by the module are very convenient.

HMAC_SHA-1

import crypto from 'crypto'

function hmacSha1(key: string, value: string) {
  const hmac = ('sha1', key)
  (value) // Set the string used to calculate the checksum value.
  return ('base64') // Calculate the checksum and return it as base64.
}

MD5

import crypto from 'crypto'

function MD5(value: string) {
  const md5 = ('md5')
  (value) // Set the string used to calculate the MD5 value.
  return ('hex') // Calculate the MD5 value and return it as a hexadecimal string.
}

security issue

For storing sensitive information such as account numbers & passwords, you can use the account and password management capabilities provided by your browser.

For example, Chrome provides thePasswordCredential Related APIs.

The call will evoke the stored popup.

ultimate

To summarize: it's also available in the browserAPIs provided to accomplish common cryptographic algorithm calls, as well as theThe Web Worker uses the, which can be effective in improving performance.

The current version of the map bed, should not be the final version, the subsequent plan will be part of the management functions in some form possible to complete the purely static support.

Feel free to share ideas & opinions in the comments section!