Skip to content

Commit

Permalink
pref: Migrated from RSA to ECC
Browse files Browse the repository at this point in the history
  • Loading branch information
[email protected] committed Feb 11, 2024
1 parent 6889c4d commit 0a6e8e3
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 49 deletions.
14 changes: 5 additions & 9 deletions apps/api/src/common/create-key-pair.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import { generateKeyPairSync } from 'crypto'
import eccrypto from 'eccrypto'

export const createKeyPair = (): {
publicKey: string
privateKey: string
} => {
const { publicKey, privateKey } = generateKeyPairSync('rsa', {
modulusLength: 2048
})

const publicKeyPEM = publicKey.export({ type: 'pkcs1', format: 'pem' })
const privateKeyPEM = privateKey.export({ type: 'pkcs1', format: 'pem' })
const privateKey = eccrypto.generatePrivate()
const publicKey = eccrypto.getPublic(privateKey)

return {
publicKey: publicKeyPEM.toString(),
privateKey: privateKeyPEM.toString()
publicKey: publicKey.toString('hex'),
privateKey: privateKey.toString('hex')
}
}
28 changes: 19 additions & 9 deletions apps/api/src/common/decrypt.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import { createPrivateKey, privateDecrypt } from 'crypto'
import eccrypto from 'eccrypto'

export const decrypt = (privateKey: string, data: string): string => {
const privateKeyPEM = createPrivateKey({
key: privateKey,
format: 'pem'
})
export const decrypt = async (
privateKey: string,
data: string
): Promise<string> => {
const parsed = JSON.parse(data)

const buffer = Buffer.from(data, 'base64')
const decrypted = privateDecrypt(privateKeyPEM, buffer)
return decrypted.toString('utf8')
const eicesData = {
iv: Buffer.from(parsed.iv),
ephemPublicKey: Buffer.from(parsed.ephemPublicKey),
ciphertext: Buffer.from(parsed.ciphertext),
mac: Buffer.from(parsed.mac)
}

const decrypted = await eccrypto.decrypt(
Buffer.from(privateKey, 'hex'),
eicesData
)

return decrypted.toString()
}
19 changes: 10 additions & 9 deletions apps/api/src/common/encrypt.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { createPublicKey, publicEncrypt } from 'crypto'
import eccrypto from 'eccrypto'

export const encrypt = (publicKey: string, data: string): string => {
const publicKeyPEM = createPublicKey({
key: publicKey,
format: 'pem'
})
export const encrypt = async (
publicKey: string,
data: string
): Promise<string> => {
const encrypted = await eccrypto.encrypt(
Buffer.from(publicKey, 'hex'),
Buffer.from(data)
)

const messageBuffer = Buffer.from(data)
const encrypted = publicEncrypt(publicKeyPEM, messageBuffer)
return encrypted.toString('base64')
return JSON.stringify(encrypted)
}
14 changes: 6 additions & 8 deletions apps/api/src/common/util.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,20 @@ describe('util', () => {
expect(keyPair.privateKey).toBeDefined()
})

it('should encrypt and decrypt a string', () => {
it('should encrypt and decrypt a string', async () => {
const keyPair = createKeyPair()
const plaintext = 'hello world'
const encrypted = encrypt(keyPair.publicKey, plaintext)
const decrypted = decrypt(keyPair.privateKey, encrypted)
const encrypted = await encrypt(keyPair.publicKey, plaintext)
const decrypted = await decrypt(keyPair.privateKey, encrypted)
expect(decrypted).toEqual(plaintext)
})

it('should fail to encrypt and decrypt a string', () => {
it('should fail to encrypt and decrypt a string', async () => {
const keyPair = createKeyPair()
const differenetKeyPair = createKeyPair()
const plainText = 'hello world'
const encrypted = encrypt(keyPair.publicKey, plainText)
const decrypted = () => {
decrypt(differenetKeyPair.privateKey, encrypted);
};
const encrypted = await encrypt(keyPair.publicKey, plainText)
const decrypted = await decrypt(differenetKeyPair.privateKey, encrypted)
expect(decrypted).toThrow()
})

Expand Down
4 changes: 2 additions & 2 deletions apps/api/src/project/service/project.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,8 @@ export class ProjectService {
for (const version of versions) {
updatedVersions.push({
id: version.id,
value: encrypt(
decrypt(project.privateKey, version.value),
value: await encrypt(
await decrypt(project.privateKey, version.value),
privateKey
)
})
Expand Down
10 changes: 5 additions & 5 deletions apps/api/src/secret/service/secret.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export class SecretService {
rotateAt: addHoursToDate(dto.rotateAfter),
versions: {
create: {
value: encrypt(project.publicKey, dto.value),
value: await encrypt(project.publicKey, dto.value),
version: 1,
createdById: user.id
}
Expand Down Expand Up @@ -170,7 +170,7 @@ export class SecretService {
lastUpdatedById: user.id,
versions: {
create: {
value: encrypt(secret.project.publicKey, dto.value),
value: await encrypt(secret.project.publicKey, dto.value),
version: previousVersion.version + 1,
createdById: user.id
}
Expand Down Expand Up @@ -356,7 +356,7 @@ export class SecretService {

if (decryptValue) {
// Decrypt the secret value
const decryptedValue = decrypt(
const decryptedValue = await decrypt(
project.privateKey,
secret.versions[0].value
)
Expand Down Expand Up @@ -447,10 +447,10 @@ export class SecretService {
})) as SecretWithVersion[]

// Return the secrets
return secrets.map((secret) => {
return secrets.map(async (secret) => {
if (decryptValue) {
// Decrypt the secret value
const decryptedValue = decrypt(
const decryptedValue = await decrypt(
project.privateKey,
secret.versions[0].value
)
Expand Down
15 changes: 8 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,13 @@
"ts-jest": "^29.1.1",
"ts-node": "10.9.1",
"typescript": "~5.2.2",
"url-loader": "^4.1.1"
"url-loader": "^4.1.1",
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/commit-analyzer": "^11.1.0",
"@semantic-release/git": "^10.0.1",
"@semantic-release/release-notes-generator": "^12.1.0",
"@types/jsonwebtoken": "^9.0.5",
"@types/eccrypto": "^1.1.6"
},
"dependencies": {
"@nestjs/common": "^10.3.0",
Expand All @@ -177,18 +183,13 @@
"@nestjs/schedule": "^4.0.0",
"@nestjs/swagger": "^7.1.17",
"@prisma/client": "^5.7.1",
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/commit-analyzer": "^11.1.0",
"@semantic-release/git": "^10.0.1",
"@semantic-release/release-notes-generator": "^12.1.0",
"@supabase/supabase-js": "^2.39.2",
"@types/jsonwebtoken": "^9.0.5",
"axios": "^1.6.5",
"chalk": "4.1.2",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
"conventional-changelog-conventionalcommits": "^7.0.2",
"dotenv": "^16.3.1",
"eccrypto": "^1.1.6",
"express": "^4.18.2",
"husky": "^8.0.3",
"jest-mock-extended": "^3.0.5",
Expand Down

0 comments on commit 0a6e8e3

Please sign in to comment.