mirror of
https://github.com/whowechina/diva_pico.git
synced 2026-10-07 06:08:10 +03:00
Parse RSA key at the packer side
This commit is contained in:
@@ -1,12 +1,8 @@
|
||||
set(BTSTACK_ROOT ${PICO_SDK_PATH}/lib/btstack)
|
||||
set(LWIP_ROOT ${PICO_SDK_PATH}/lib/lwip)
|
||||
|
||||
function(make_firmware board board_def)
|
||||
pico_sdk_init()
|
||||
add_executable(${board}
|
||||
main.c slider.c rgb.c button.c savedata.c config.c commands.c
|
||||
cli.c mpr121.c hebtn.c lzfx.c usb_descriptors.c ps4_feat.c gesture.c
|
||||
ps4key.c)
|
||||
ps4key.c crypto/ps4_crypto.c)
|
||||
target_compile_definitions(${board} PUBLIC ${board_def})
|
||||
pico_enable_stdio_usb(${board} 1)
|
||||
pico_enable_stdio_uart(${board} 0)
|
||||
@@ -15,13 +11,10 @@ function(make_firmware board board_def)
|
||||
|
||||
target_compile_options(${board} PRIVATE -Wall -Werror -Wfatal-errors -O3)
|
||||
target_include_directories(${board} PRIVATE ${CMAKE_CURRENT_LIST_DIR})
|
||||
target_include_directories(${board} PRIVATE
|
||||
${BTSTACK_ROOT}/src
|
||||
${LWIP_ROOT}/src/include)
|
||||
|
||||
target_link_libraries(${board} PRIVATE
|
||||
pico_multicore pico_stdlib hardware_pio hardware_pwm hardware_flash
|
||||
hardware_adc hardware_i2c hardware_watchdog
|
||||
hardware_adc hardware_i2c hardware_watchdog pico_rand pico_mbedtls
|
||||
tinyusb_device tinyusb_board)
|
||||
|
||||
pico_add_extra_outputs(${board})
|
||||
|
||||
+23
-2
@@ -13,6 +13,7 @@
|
||||
#include "savedata.h"
|
||||
#include "cli.h"
|
||||
#include "ps4key.h"
|
||||
#include "crypto/ps4_crypto.h"
|
||||
|
||||
#include "gesture.h"
|
||||
|
||||
@@ -462,8 +463,27 @@ static void handle_ps4key(int argc, char *argv[])
|
||||
}
|
||||
|
||||
savedata_write_global(&key, sizeof(key));
|
||||
printf("PS4 key stored: Serial: %s, PEM: %d bytes, sig: %d bytes\n",
|
||||
ps4key_get_serial(&key), key.pem_len - 1, key.sig_len);
|
||||
printf("PS4 key stored: Serial: %s, sig: %d bytes, N/E/P/Q: %d/%d/%d/%d bytes\n",
|
||||
ps4key_get_serial(&key),
|
||||
key.sig_len,
|
||||
key.rsa_n_len,
|
||||
key.rsa_e_len,
|
||||
key.rsa_p_len,
|
||||
key.rsa_q_len);
|
||||
}
|
||||
|
||||
static void handle_rsa(int argc, char *argv[])
|
||||
{
|
||||
(void)argv;
|
||||
if (argc != 0) {
|
||||
printf("Usage: rsa\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ps4_crypto_selftest()) {
|
||||
printf("PS4 crypto selftest failed.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void commands_init()
|
||||
@@ -482,4 +502,5 @@ void commands_init()
|
||||
cli_register("save", handle_save, "Save config to flash.");
|
||||
cli_register("factory", handle_factory_reset, "Reset everything to default.");
|
||||
cli_register("ps4key", handle_ps4key, "Import or clear serialized PS4 key data.");
|
||||
cli_register("rsa", handle_rsa, "Run hello-world SHA256, nonce SHA256, and RSA context smoke test.");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/* This can be enabled lated when we use SNTP */
|
||||
#undef MBEDTLS_HAVE_TIME_DATE
|
||||
|
||||
#define MBEDTLS_CHECK_PARAMS_ASSERT
|
||||
#define MBEDTLS_ENTROPY_HARDWARE_ALT
|
||||
#define MBEDTLS_AES_ROM_TABLES
|
||||
#define MBEDTLS_AES_FEWER_TABLES
|
||||
#define MBEDTLS_CAMELLIA_SMALL_MEMORY
|
||||
#define MBEDTLS_CHECK_RETURN_WARNING
|
||||
#undef MBEDTLS_FS_IO
|
||||
#define MBEDTLS_NO_PLATFORM_ENTROPY
|
||||
#undef MBEDTLS_PSA_CRYPTO_CLIENT
|
||||
#undef MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_RSA_C
|
||||
#define MBEDTLS_X509_RSASSA_PSS_SUPPORT
|
||||
#define MBEDTLS_PKCS1_V21
|
||||
#define MBEDTLS_BIGNUM_C
|
||||
#define MBEDTLS_MD_C
|
||||
#define MBEDTLS_SSL_ASYNC_PRIVATE
|
||||
#define MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH
|
||||
#undef MBEDTLS_USE_PSA_CRYPTO
|
||||
#define MBEDTLS_OID_C
|
||||
#define MBEDTLS_X509_CRT_PARSE_C
|
||||
#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
|
||||
#define MBEDTLS_X509_USE_C
|
||||
#define MBEDTLS_ASN1_PARSE_C
|
||||
#define MBEDTLS_BASE64_C
|
||||
#define MBEDTLS_PEM_PARSE_C
|
||||
#define MBEDTLS_PEM_WRITE_C
|
||||
#define MBEDTLS_PK_PARSE_C
|
||||
#define MBEDTLS_PK_WRITE_C
|
||||
#define MBEDTLS_PKCS1_PARSE_C
|
||||
#define MBEDTLS_PK_C
|
||||
#undef MBEDTLS_NET_C
|
||||
#undef MBEDTLS_PSA_CRYPTO_STORAGE_C
|
||||
#undef MBEDTLS_PSA_ITS_FILE_C
|
||||
#undef MBEDTLS_TIMING_C
|
||||
+139
-18
@@ -7,6 +7,9 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mbedtls/pk.h"
|
||||
#include "mbedtls/rsa.h"
|
||||
|
||||
#include "ps4key.h"
|
||||
|
||||
static uint32_t crc32_calc(const uint8_t *data, size_t size)
|
||||
@@ -122,10 +125,86 @@ static bool serial_is_valid(const uint8_t *serial, size_t size)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool pem_is_valid(const char *pem)
|
||||
static size_t key_payload_len(const ps4key_t *key)
|
||||
{
|
||||
return strstr(pem, "-----BEGIN RSA PRIVATE KEY-----") &&
|
||||
strstr(pem, "-----END RSA PRIVATE KEY-----");
|
||||
return key->serial_len + key->sig_len +
|
||||
key->rsa_n_len + key->rsa_e_len +
|
||||
key->rsa_p_len + key->rsa_q_len;
|
||||
}
|
||||
|
||||
static size_t sig_offset(const ps4key_t *key)
|
||||
{
|
||||
return key->serial_len;
|
||||
}
|
||||
|
||||
static size_t rsa_n_offset(const ps4key_t *key)
|
||||
{
|
||||
return sig_offset(key) + key->sig_len;
|
||||
}
|
||||
|
||||
static size_t rsa_e_offset(const ps4key_t *key)
|
||||
{
|
||||
return rsa_n_offset(key) + key->rsa_n_len;
|
||||
}
|
||||
|
||||
static size_t rsa_p_offset(const ps4key_t *key)
|
||||
{
|
||||
return rsa_e_offset(key) + key->rsa_e_len;
|
||||
}
|
||||
|
||||
static size_t rsa_q_offset(const ps4key_t *key)
|
||||
{
|
||||
return rsa_p_offset(key) + key->rsa_p_len;
|
||||
}
|
||||
|
||||
static bool rebuild_pem(const ps4key_t *key, char *pem, size_t pem_size)
|
||||
{
|
||||
mbedtls_mpi n;
|
||||
mbedtls_mpi e;
|
||||
mbedtls_mpi p;
|
||||
mbedtls_mpi q;
|
||||
mbedtls_mpi_init(&n);
|
||||
mbedtls_mpi_init(&e);
|
||||
mbedtls_mpi_init(&p);
|
||||
mbedtls_mpi_init(&q);
|
||||
|
||||
int ret = mbedtls_mpi_read_binary(&n, ps4key_get_rsa_n(key), key->rsa_n_len);
|
||||
if (ret != 0) goto cleanup;
|
||||
ret = mbedtls_mpi_read_binary(&e, ps4key_get_rsa_e(key), key->rsa_e_len);
|
||||
if (ret != 0) goto cleanup;
|
||||
ret = mbedtls_mpi_read_binary(&p, ps4key_get_rsa_p(key), key->rsa_p_len);
|
||||
if (ret != 0) goto cleanup;
|
||||
ret = mbedtls_mpi_read_binary(&q, ps4key_get_rsa_q(key), key->rsa_q_len);
|
||||
if (ret != 0) goto cleanup;
|
||||
|
||||
mbedtls_pk_context pk;
|
||||
mbedtls_pk_init(&pk);
|
||||
|
||||
ret = mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA));
|
||||
if (ret != 0) {
|
||||
mbedtls_pk_free(&pk);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
mbedtls_rsa_context *rsa = mbedtls_pk_rsa(pk);
|
||||
mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
|
||||
|
||||
ret = mbedtls_rsa_import(rsa, &n, &p, &q, NULL, &e);
|
||||
if (ret == 0) {
|
||||
ret = mbedtls_rsa_complete(rsa);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = mbedtls_pk_write_key_pem(&pk, (unsigned char *)pem, pem_size);
|
||||
}
|
||||
|
||||
mbedtls_pk_free(&pk);
|
||||
|
||||
cleanup:
|
||||
mbedtls_mpi_free(&n);
|
||||
mbedtls_mpi_free(&e);
|
||||
mbedtls_mpi_free(&p);
|
||||
mbedtls_mpi_free(&q);
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
static void set_error(const char **error, const char *message)
|
||||
@@ -149,13 +228,16 @@ static bool ps4key_validate(const ps4key_t *key, const char **error)
|
||||
}
|
||||
|
||||
if ((key->serial_len != (PS4KEY_SERIAL_LENGTH + 1)) ||
|
||||
(key->pem_len <= 1) || (key->pem_len > (PS4KEY_PEM_MAX_LENGTH + 1)) ||
|
||||
(key->sig_len == 0) || (key->sig_len > PS4KEY_SIG_MAX_LENGTH)) {
|
||||
(key->sig_len != PS4KEY_SIG_LENGTH) ||
|
||||
(key->rsa_n_len != PS4KEY_RSA_N_LENGTH) ||
|
||||
(key->rsa_e_len == 0) || (key->rsa_e_len > PS4KEY_RSA_E_LENGTH) ||
|
||||
(key->rsa_p_len != PS4KEY_RSA_P_LENGTH) ||
|
||||
(key->rsa_q_len != PS4KEY_RSA_Q_LENGTH)) {
|
||||
set_error(error, "Serialized part lengths are invalid.");
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t payload_len = key->serial_len + key->pem_len + key->sig_len;
|
||||
size_t payload_len = key_payload_len(key);
|
||||
if (payload_len > sizeof(key->payload)) {
|
||||
set_error(error, "Serialized length mismatch.");
|
||||
return false;
|
||||
@@ -171,14 +253,9 @@ static bool ps4key_validate(const ps4key_t *key, const char **error)
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint8_t *pem_ptr = key->payload + key->serial_len;
|
||||
if (pem_ptr[key->pem_len - 1] != '\0') {
|
||||
set_error(error, "PEM data is not null terminated.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!pem_is_valid((const char *)pem_ptr)) {
|
||||
set_error(error, "PEM content does not look like an RSA private key.");
|
||||
size_t rsa_q_end = rsa_q_offset(key) + key->rsa_q_len;
|
||||
if (rsa_q_end != payload_len) {
|
||||
set_error(error, "Serialized layout mismatch.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -211,7 +288,7 @@ bool ps4key_parse_text(const char *text, ps4key_t *key, const char **error)
|
||||
return false;
|
||||
}
|
||||
const ps4key_t *src = (const ps4key_t *)decoded;
|
||||
size_t payload_len = src->serial_len + src->pem_len + src->sig_len;
|
||||
size_t payload_len = key_payload_len(src);
|
||||
if (decoded_len != header_len + payload_len) {
|
||||
set_error(error, "Serialized length mismatch.");
|
||||
return false;
|
||||
@@ -238,10 +315,22 @@ const char *ps4key_get_serial(const ps4key_t *key)
|
||||
|
||||
const char *ps4key_get_pem(const ps4key_t *key)
|
||||
{
|
||||
if (key == NULL) {
|
||||
static char pem[2048] = {0};
|
||||
static uint32_t last_crc = 0;
|
||||
|
||||
if ((key == NULL) || !ps4key_key_valid(key)) {
|
||||
return NULL;
|
||||
}
|
||||
return (const char *)(key->payload + key->serial_len);
|
||||
|
||||
if ((last_crc != key->crc32) || (pem[0] == '\0')) {
|
||||
memset(pem, 0, sizeof(pem));
|
||||
if (!rebuild_pem(key, pem, sizeof(pem))) {
|
||||
return NULL;
|
||||
}
|
||||
last_crc = key->crc32;
|
||||
}
|
||||
|
||||
return pem;
|
||||
}
|
||||
|
||||
const uint8_t *ps4key_get_sig(const ps4key_t *key)
|
||||
@@ -249,7 +338,7 @@ const uint8_t *ps4key_get_sig(const ps4key_t *key)
|
||||
if (key == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return key->payload + key->serial_len + key->pem_len;
|
||||
return key->payload + sig_offset(key);
|
||||
}
|
||||
|
||||
size_t ps4key_get_sig_len(const ps4key_t *key)
|
||||
@@ -259,3 +348,35 @@ size_t ps4key_get_sig_len(const ps4key_t *key)
|
||||
}
|
||||
return key->sig_len;
|
||||
}
|
||||
|
||||
const uint8_t *ps4key_get_rsa_n(const ps4key_t *key)
|
||||
{
|
||||
if (key == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return key->payload + rsa_n_offset(key);
|
||||
}
|
||||
|
||||
const uint8_t *ps4key_get_rsa_e(const ps4key_t *key)
|
||||
{
|
||||
if (key == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return key->payload + rsa_e_offset(key);
|
||||
}
|
||||
|
||||
const uint8_t *ps4key_get_rsa_p(const ps4key_t *key)
|
||||
{
|
||||
if (key == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return key->payload + rsa_p_offset(key);
|
||||
}
|
||||
|
||||
const uint8_t *ps4key_get_rsa_q(const ps4key_t *key)
|
||||
{
|
||||
if (key == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return key->payload + rsa_q_offset(key);
|
||||
}
|
||||
|
||||
+16
-4
@@ -14,17 +14,25 @@
|
||||
#define PS4KEY_STORAGE_MAGIC 0x4b345350u
|
||||
#define PS4KEY_STORAGE_VERSION 1u
|
||||
#define PS4KEY_SERIAL_LENGTH 16
|
||||
#define PS4KEY_PEM_MAX_LENGTH 2048
|
||||
#define PS4KEY_SIG_MAX_LENGTH 512
|
||||
#define PS4KEY_PAYLOAD_MAX_LENGTH (PS4KEY_SERIAL_LENGTH + 1 + PS4KEY_PEM_MAX_LENGTH + 1 + PS4KEY_SIG_MAX_LENGTH)
|
||||
#define PS4KEY_SIG_LENGTH 256
|
||||
#define PS4KEY_RSA_N_LENGTH 256
|
||||
#define PS4KEY_RSA_E_LENGTH 4
|
||||
#define PS4KEY_RSA_P_LENGTH 128
|
||||
#define PS4KEY_RSA_Q_LENGTH 128
|
||||
#define PS4KEY_PAYLOAD_MAX_LENGTH (PS4KEY_SERIAL_LENGTH + 1 + PS4KEY_SIG_LENGTH + \
|
||||
PS4KEY_RSA_N_LENGTH + PS4KEY_RSA_E_LENGTH + \
|
||||
PS4KEY_RSA_P_LENGTH + PS4KEY_RSA_Q_LENGTH)
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t magic;
|
||||
uint8_t version;
|
||||
uint8_t reserved;
|
||||
uint16_t serial_len;
|
||||
uint16_t pem_len;
|
||||
uint16_t sig_len;
|
||||
uint16_t rsa_n_len;
|
||||
uint16_t rsa_e_len;
|
||||
uint16_t rsa_p_len;
|
||||
uint16_t rsa_q_len;
|
||||
uint32_t crc32;
|
||||
uint8_t payload[PS4KEY_PAYLOAD_MAX_LENGTH];
|
||||
} ps4key_t;
|
||||
@@ -36,5 +44,9 @@ const char *ps4key_get_serial(const ps4key_t *key);
|
||||
const char *ps4key_get_pem(const ps4key_t *key);
|
||||
const uint8_t *ps4key_get_sig(const ps4key_t *key);
|
||||
size_t ps4key_get_sig_len(const ps4key_t *key);
|
||||
const uint8_t *ps4key_get_rsa_n(const ps4key_t *key);
|
||||
const uint8_t *ps4key_get_rsa_e(const ps4key_t *key);
|
||||
const uint8_t *ps4key_get_rsa_p(const ps4key_t *key);
|
||||
const uint8_t *ps4key_get_rsa_q(const ps4key_t *key);
|
||||
|
||||
#endif
|
||||
+121
-19
@@ -278,8 +278,11 @@
|
||||
<script>
|
||||
const PREFIX = "PS4K1";
|
||||
const SERIAL_LENGTH = 16;
|
||||
const PEM_MAX_LENGTH = 2048;
|
||||
const SIG_MAX_LENGTH = 512;
|
||||
const SIG_LENGTH = 256;
|
||||
const RSA_N_LENGTH = 256;
|
||||
const RSA_E_LENGTH = 4;
|
||||
const RSA_P_LENGTH = 128;
|
||||
const RSA_Q_LENGTH = 128;
|
||||
|
||||
const sigFileInput = document.getElementById("sigFile");
|
||||
const serialFileInput = document.getElementById("serialFile");
|
||||
@@ -320,8 +323,8 @@
|
||||
if (!sigBytes || sigBytes.length === 0) {
|
||||
throw new Error("Please upload the signature.bin file.");
|
||||
}
|
||||
if (sigBytes.length > SIG_MAX_LENGTH) {
|
||||
throw new Error(`signature.bin is too large, max ${SIG_MAX_LENGTH} bytes.`);
|
||||
if (sigBytes.length !== SIG_LENGTH) {
|
||||
throw new Error(`signature.bin must be exactly ${SIG_LENGTH} bytes.`);
|
||||
}
|
||||
if (!/^\d{16}$/.test(serial)) {
|
||||
throw new Error("serial.txt must be a 16-digit decimal string.");
|
||||
@@ -330,9 +333,98 @@
|
||||
!pem.includes("-----END RSA PRIVATE KEY-----")) {
|
||||
throw new Error("key.pem must contain BEGIN/END RSA PRIVATE KEY markers.");
|
||||
}
|
||||
if (pem.length === 0 || pem.length > PEM_MAX_LENGTH) {
|
||||
throw new Error(`key.pem length must be 1-${PEM_MAX_LENGTH} characters.`);
|
||||
}
|
||||
|
||||
function base64ToBytes(text) {
|
||||
const binary = atob(text.replace(/\s+/g, ""));
|
||||
const bytes = new Uint8Array(binary.length);
|
||||
for (let i = 0; i < binary.length; i++) {
|
||||
bytes[i] = binary.charCodeAt(i);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function parseLength(bytes, pos) {
|
||||
if (pos >= bytes.length) {
|
||||
throw new Error("Invalid DER: length overflow.");
|
||||
}
|
||||
const first = bytes[pos++];
|
||||
if ((first & 0x80) === 0) {
|
||||
return { len: first, pos };
|
||||
}
|
||||
const count = first & 0x7f;
|
||||
if (count === 0 || count > 4 || pos + count > bytes.length) {
|
||||
throw new Error("Invalid DER: unsupported length.");
|
||||
}
|
||||
let len = 0;
|
||||
for (let i = 0; i < count; i++) {
|
||||
len = (len << 8) | bytes[pos++];
|
||||
}
|
||||
return { len, pos };
|
||||
}
|
||||
|
||||
function readTlv(bytes, pos, expectedTag) {
|
||||
if (pos >= bytes.length || bytes[pos] !== expectedTag) {
|
||||
throw new Error(`Invalid DER: expected tag 0x${expectedTag.toString(16)}.`);
|
||||
}
|
||||
pos += 1;
|
||||
const parsed = parseLength(bytes, pos);
|
||||
const len = parsed.len;
|
||||
pos = parsed.pos;
|
||||
const end = pos + len;
|
||||
if (end > bytes.length) {
|
||||
throw new Error("Invalid DER: truncated value.");
|
||||
}
|
||||
return { value: bytes.subarray(pos, end), end };
|
||||
}
|
||||
|
||||
function trimInteger(bytes) {
|
||||
let i = 0;
|
||||
while (i < bytes.length - 1 && bytes[i] === 0) {
|
||||
i += 1;
|
||||
}
|
||||
return bytes.subarray(i);
|
||||
}
|
||||
|
||||
function toFixedWidth(bytes, width, name) {
|
||||
const value = trimInteger(bytes);
|
||||
if (value.length > width) {
|
||||
throw new Error(`${name} is too large (${value.length} > ${width}).`);
|
||||
}
|
||||
const out = new Uint8Array(width);
|
||||
out.set(value, width - value.length);
|
||||
return out;
|
||||
}
|
||||
|
||||
function parsePkcs1PrivateKey(pem) {
|
||||
const base64 = pem
|
||||
.replace(/-----BEGIN RSA PRIVATE KEY-----/g, "")
|
||||
.replace(/-----END RSA PRIVATE KEY-----/g, "")
|
||||
.replace(/\s+/g, "");
|
||||
const der = base64ToBytes(base64);
|
||||
|
||||
const seq = readTlv(der, 0, 0x30);
|
||||
let pos = 0;
|
||||
const body = seq.value;
|
||||
|
||||
const version = readTlv(body, pos, 0x02);
|
||||
pos = version.end;
|
||||
const n = readTlv(body, pos, 0x02);
|
||||
pos = n.end;
|
||||
const e = readTlv(body, pos, 0x02);
|
||||
pos = e.end;
|
||||
const d = readTlv(body, pos, 0x02);
|
||||
pos = d.end;
|
||||
const p = readTlv(body, pos, 0x02);
|
||||
pos = p.end;
|
||||
const q = readTlv(body, pos, 0x02);
|
||||
|
||||
return {
|
||||
n: toFixedWidth(n.value, RSA_N_LENGTH, "rsaN"),
|
||||
e: toFixedWidth(e.value, RSA_E_LENGTH, "rsaE"),
|
||||
p: toFixedWidth(p.value, RSA_P_LENGTH, "rsaP"),
|
||||
q: toFixedWidth(q.value, RSA_Q_LENGTH, "rsaQ"),
|
||||
};
|
||||
}
|
||||
|
||||
function crc32(bytes) {
|
||||
@@ -356,28 +448,38 @@
|
||||
return btoa(binary);
|
||||
}
|
||||
|
||||
function packPayload(serial, pem, sigBytes) {
|
||||
function packPayload(serial, sigBytes, rsa) {
|
||||
const serialBytes = encoder.encode(serial);
|
||||
const pemBytes = encoder.encode(pem);
|
||||
const serialLen = serialBytes.length + 1;
|
||||
const pemLen = pemBytes.length + 1;
|
||||
const payloadLength = serialLen + pemLen + sigBytes.length;
|
||||
const payloadLength = serialLen + sigBytes.length +
|
||||
rsa.n.length + rsa.e.length +
|
||||
rsa.p.length + rsa.q.length;
|
||||
const payload = new Uint8Array(payloadLength);
|
||||
payload.set(serialBytes, 0);
|
||||
payload[serialBytes.length] = 0;
|
||||
payload.set(pemBytes, serialLen);
|
||||
payload[serialLen + pemBytes.length] = 0;
|
||||
payload.set(sigBytes, serialLen + pemLen);
|
||||
let offset = serialLen;
|
||||
payload.set(sigBytes, offset);
|
||||
offset += sigBytes.length;
|
||||
payload.set(rsa.n, offset);
|
||||
offset += rsa.n.length;
|
||||
payload.set(rsa.e, offset);
|
||||
offset += rsa.e.length;
|
||||
payload.set(rsa.p, offset);
|
||||
offset += rsa.p.length;
|
||||
payload.set(rsa.q, offset);
|
||||
|
||||
const header = new Uint8Array(16);
|
||||
const header = new Uint8Array(22);
|
||||
header.set([0x50, 0x53, 0x34, 0x4b], 0);
|
||||
header[4] = 1;
|
||||
header[5] = 0;
|
||||
const view = new DataView(header.buffer);
|
||||
view.setUint16(6, serialLen, true);
|
||||
view.setUint16(8, pemLen, true);
|
||||
view.setUint16(10, sigBytes.length, true);
|
||||
view.setUint32(12, crc32(payload), true);
|
||||
view.setUint16(8, sigBytes.length, true);
|
||||
view.setUint16(10, rsa.n.length, true);
|
||||
view.setUint16(12, rsa.e.length, true);
|
||||
view.setUint16(14, rsa.p.length, true);
|
||||
view.setUint16(16, rsa.q.length, true);
|
||||
view.setUint32(18, crc32(payload), true);
|
||||
|
||||
const packed = new Uint8Array(header.length + payload.length);
|
||||
packed.set(header, 0);
|
||||
@@ -437,8 +539,8 @@
|
||||
const pem = pemText ? normalizePem(pemText) : "";
|
||||
|
||||
assertInputs(serial, pem, sigBytes);
|
||||
|
||||
const packed = packPayload(serial, pem, sigBytes);
|
||||
const rsa = parsePkcs1PrivateKey(pem);
|
||||
const packed = packPayload(serial, sigBytes, rsa);
|
||||
output.value = packed;
|
||||
setStatus("ok", `Packed successfully, total ${packed.length} chars.`);
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user