Skip to content

Commit

Permalink
Working version Android and iOS
Browse files Browse the repository at this point in the history
  • Loading branch information
yagopv committed Nov 18, 2024
1 parent 3a5b1f8 commit 2643fae
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 20 deletions.
1 change: 1 addition & 0 deletions packages/protocol-kit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
},
"dependencies": {
"@noble/curves": "^1.6.0",
"@peculiar/asn1-schema": "^2.3.13",
"@safe-global/safe-deployments": "^1.37.14",
"@safe-global/safe-modules-deployments": "^2.2.4",
"@safe-global/types-kit": "^1.0.0",
Expand Down
63 changes: 46 additions & 17 deletions packages/protocol-kit/src/utils/passkeys/extractPasskeyData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,25 @@ import { Buffer } from 'buffer'
import { p256 } from '@noble/curves/p256'
import { getFCLP256VerifierDeployment } from '@safe-global/safe-modules-deployments'
import { PasskeyArgType, PasskeyCoordinates } from '@safe-global/protocol-kit/types'
import { AsnParser, AsnProp, AsnPropTypes, AsnType, AsnTypeTypes } from '@peculiar/asn1-schema'

@AsnType({ type: AsnTypeTypes.Sequence })
class AlgorithmIdentifier {
@AsnProp({ type: AsnPropTypes.ObjectIdentifier })
public id: string = ''

@AsnProp({ type: AsnPropTypes.ObjectIdentifier, optional: true })
public curve: string = ''
}

@AsnType({ type: AsnTypeTypes.Sequence })
class ECPublicKey {
@AsnProp({ type: AlgorithmIdentifier })
public algorithm = new AlgorithmIdentifier()

@AsnProp({ type: AsnPropTypes.BitString })
public publicKey: ArrayBuffer = new ArrayBuffer(0)
}

/**
* Converts a Base64 URL-encoded string to a Uint8Array.
Expand All @@ -21,48 +40,58 @@ function base64ToUint8Array(base64: string): Uint8Array {
}

/**
* Ensures the elliptic curve public key is in the correct uncompressed format.
* Formats the public key to ensure it is in the correct uncompressed format.
*
* Elliptic curve operations often require the public key to be in an uncompressed format,
* which starts with a `0x04` byte, followed by the x and y coordinates. This function
* checks the key length and prepends `0x04` if necessary.
* If the public key is in ASN.1 DER format, it extracts the key. If the key is 64 bytes,
* it prepends 0x04 to indicate it's uncompressed. This is necessary for compatibility
* with elliptic curve operations.
*
* @param {Uint8Array} publicKey - The public key to format.
* @param {Uint8Array} publicKeyBytes - The public key bytes to format.
* @returns {Uint8Array} The formatted public key in uncompressed format.
*/
function ensureCorrectFormat(publicKey: Uint8Array): Uint8Array {
if (publicKey.length === 64) {
function formatPublicKey(publicKeyBytes: Uint8Array): Uint8Array {
// ASN.1 DER encoding of an EC public key
// Android Keystore returns the public key in ASN.1 DER format
// https://developer.android.com/privacy-and-security/keystore#ImportingEncryptedKeys
if (publicKeyBytes.length > 65) {
const decodedPublicKey = AsnParser.parse(publicKeyBytes.buffer, ECPublicKey)

return new Uint8Array(decodedPublicKey.publicKey)
}

// Missing prefix
if (publicKeyBytes.length === 64) {
const uncompressedKey = new Uint8Array(65)
uncompressedKey[0] = 0x04
uncompressedKey.set(publicKey, 1)
uncompressedKey.set(publicKeyBytes, 1)

return uncompressedKey
}

return publicKey
return publicKeyBytes
}

/**
* Decodes a Base64-encoded ECDSA public key for React Native and extracts the x and y coordinates.
*
* This function decodes a Base64-encoded public key, ensures it is in the correct uncompressed format,
* and extracts the x and y coordinates using the `@noble/curves` library. The coordinates are returned
* as hexadecimal strings prefixed with '0x'.
* This function decodes a Base64-encoded public key, formats it to ensure compatibility with
* elliptic curve operations, and extracts the x and y coordinates using the `@noble/curves` library.
* The coordinates are returned as hexadecimal strings prefixed with '0x'.
*
* @param {string} publicKey - The Base64-encoded public key to decode.
* @returns {PasskeyCoordinates} An object containing the x and y coordinates of the public key.
* @throws {Error} Throws an error if the key coordinates cannot be extracted.
*/
function decodePublicKeyForReactNative(publicKey: string): PasskeyCoordinates {
const publicKeyUint8Array = base64ToUint8Array(publicKey)

if (publicKeyUint8Array.length === 0) {
const publicKeyBytes = base64ToUint8Array(publicKey)
console.log('publicKey', publicKey, publicKeyBytes)
if (publicKeyBytes.length === 0) {
throw new Error('Decoded public key is empty.')
}

const formattedKey = ensureCorrectFormat(publicKeyUint8Array)
const formattedPublicKeyBytes = formatPublicKey(publicKeyBytes)

const point = p256.ProjectivePoint.fromHex(formattedKey)
const point = p256.ProjectivePoint.fromHex(formattedPublicKeyBytes)

const x = point.x.toString(16).padStart(64, '0')
const y = point.y.toString(16).padStart(64, '0')
Expand Down
4 changes: 1 addition & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1175,7 +1175,7 @@
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426"
integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==

"@noble/[email protected]", "@noble/hashes@^1.3.3", "@noble/hashes@^1.4.0", "@noble/hashes@~1.5.0":
"@noble/[email protected]", "@noble/hashes@^1.4.0", "@noble/hashes@~1.5.0":
version "1.5.0"
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.5.0.tgz#abadc5ca20332db2b1b2aa3e496e9af1213570b0"
integrity sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==
Expand Down Expand Up @@ -1745,8 +1745,6 @@
version "5.0.4"
dependencies:
"@noble/curves" "^1.6.0"
"@noble/hashes" "^1.3.3"
"@peculiar/asn1-schema" "^2.3.13"
"@safe-global/safe-deployments" "^1.37.14"
"@safe-global/safe-modules-deployments" "^2.2.4"
"@safe-global/types-kit" "^1.0.0"
Expand Down

0 comments on commit 2643fae

Please sign in to comment.