|
1 |
| -import { keySplit } from '../utils/index.js'; |
2 |
| -import { base64, hex } from '../../../src/encodings/index.js'; |
3 |
| -import { Binary } from '../binary.js'; |
4 |
| -import { type SymmetricCipher } from '../ciphers/symmetric-cipher-base.js'; |
5 |
| -import { type KeyAccess, type KeyAccessObject } from './key-access.js'; |
6 |
| -import { type Policy } from './policy.js'; |
7 |
| -import { |
8 |
| - type CryptoService, |
9 |
| - type DecryptResult, |
10 |
| - type EncryptResult, |
11 |
| -} from '../crypto/declarations.js'; |
| 1 | +import { type KeyAccessObject } from './key-access.js'; |
12 | 2 | import { IntegrityAlgorithm } from '../tdf.js';
|
13 |
| -import { ConfigurationError } from '../../../src/errors.js'; |
14 |
| - |
15 |
| -export type KeyInfo = { |
16 |
| - readonly unwrappedKeyBinary: Binary; |
17 |
| - readonly unwrappedKeyIvBinary: Binary; |
18 |
| -}; |
19 | 3 |
|
20 | 4 | export type Segment = {
|
21 | 5 | readonly hash: string;
|
@@ -47,126 +31,3 @@ export type EncryptionInformation = {
|
47 | 31 | };
|
48 | 32 | policy: string;
|
49 | 33 | };
|
50 |
| - |
51 |
| -export class SplitKey { |
52 |
| - readonly cryptoService: CryptoService; |
53 |
| - keyAccess: KeyAccess[]; |
54 |
| - |
55 |
| - constructor(public readonly cipher: SymmetricCipher) { |
56 |
| - this.cryptoService = cipher.cryptoService; |
57 |
| - this.keyAccess = []; |
58 |
| - } |
59 |
| - |
60 |
| - async generateKey(): Promise<KeyInfo> { |
61 |
| - const unwrappedKey = await this.cipher.generateKey(); |
62 |
| - const unwrappedKeyBinary = Binary.fromString(hex.decode(unwrappedKey)); |
63 |
| - const unwrappedKeyIvBinary = await this.generateIvBinary(); |
64 |
| - return { unwrappedKeyBinary, unwrappedKeyIvBinary }; |
65 |
| - } |
66 |
| - |
67 |
| - async encrypt( |
68 |
| - contentBinary: Binary, |
69 |
| - keyBinary: Binary, |
70 |
| - ivBinaryOptional?: Binary |
71 |
| - ): Promise<EncryptResult> { |
72 |
| - const ivBinary = ivBinaryOptional || (await this.generateIvBinary()); |
73 |
| - return this.cipher.encrypt(contentBinary, keyBinary, ivBinary); |
74 |
| - } |
75 |
| - |
76 |
| - async decrypt(content: Uint8Array, keyBinary: Binary): Promise<DecryptResult> { |
77 |
| - return this.cipher.decrypt(content, keyBinary); |
78 |
| - } |
79 |
| - |
80 |
| - async getKeyAccessObjects(policy: Policy, keyInfo: KeyInfo): Promise<KeyAccessObject[]> { |
81 |
| - const splitIds = [...new Set(this.keyAccess.map(({ sid }) => sid))].sort((a = '', b = '') => |
82 |
| - a.localeCompare(b) |
83 |
| - ); |
84 |
| - const unwrappedKeySplitBuffers = await keySplit( |
85 |
| - new Uint8Array(keyInfo.unwrappedKeyBinary.asByteArray()), |
86 |
| - splitIds.length, |
87 |
| - this.cryptoService |
88 |
| - ); |
89 |
| - const splitsByName = Object.fromEntries( |
90 |
| - splitIds.map((sid, index) => [sid, unwrappedKeySplitBuffers[index]]) |
91 |
| - ); |
92 |
| - |
93 |
| - const keyAccessObjects = []; |
94 |
| - for (const item of this.keyAccess) { |
95 |
| - // use the key split to encrypt metadata for each key access object |
96 |
| - const unwrappedKeySplitBuffer = splitsByName[item.sid || '']; |
97 |
| - const unwrappedKeySplitBinary = Binary.fromArrayBuffer(unwrappedKeySplitBuffer.buffer); |
98 |
| - |
99 |
| - const metadata = item.metadata || ''; |
100 |
| - const metadataStr = ( |
101 |
| - typeof metadata === 'object' |
102 |
| - ? JSON.stringify(metadata) |
103 |
| - : typeof metadata === 'string' |
104 |
| - ? metadata |
105 |
| - : () => { |
106 |
| - throw new ConfigurationError( |
107 |
| - "KAO generation failure: metadata isn't a string or object" |
108 |
| - ); |
109 |
| - } |
110 |
| - ) as string; |
111 |
| - |
112 |
| - const metadataBinary = Binary.fromArrayBuffer(new TextEncoder().encode(metadataStr)); |
113 |
| - |
114 |
| - const encryptedMetadataResult = await this.encrypt( |
115 |
| - metadataBinary, |
116 |
| - unwrappedKeySplitBinary, |
117 |
| - keyInfo.unwrappedKeyIvBinary |
118 |
| - ); |
119 |
| - |
120 |
| - const encryptedMetadataOb = { |
121 |
| - ciphertext: base64.encode(encryptedMetadataResult.payload.asString()), |
122 |
| - iv: base64.encode(keyInfo.unwrappedKeyIvBinary.asString()), |
123 |
| - }; |
124 |
| - |
125 |
| - const encryptedMetadataStr = JSON.stringify(encryptedMetadataOb); |
126 |
| - const keyAccessObject = await item.write( |
127 |
| - policy, |
128 |
| - unwrappedKeySplitBuffer, |
129 |
| - encryptedMetadataStr |
130 |
| - ); |
131 |
| - keyAccessObjects.push(keyAccessObject); |
132 |
| - } |
133 |
| - |
134 |
| - return keyAccessObjects; |
135 |
| - } |
136 |
| - |
137 |
| - async generateIvBinary(): Promise<Binary> { |
138 |
| - const iv = await this.cipher.generateInitializationVector(); |
139 |
| - return Binary.fromString(hex.decode(iv)); |
140 |
| - } |
141 |
| - |
142 |
| - async write(policy: Policy, keyInfo: KeyInfo): Promise<EncryptionInformation> { |
143 |
| - const algorithm = this.cipher?.name; |
144 |
| - if (!algorithm) { |
145 |
| - // Hard coded as part of the cipher object. This should not be reachable. |
146 |
| - throw new ConfigurationError('uninitialized cipher type'); |
147 |
| - } |
148 |
| - const keyAccessObjects = await this.getKeyAccessObjects(policy, keyInfo); |
149 |
| - |
150 |
| - // For now we're only concerned with a single (first) key access object |
151 |
| - const policyForManifest = base64.encode(JSON.stringify(policy)); |
152 |
| - |
153 |
| - return { |
154 |
| - type: 'split', |
155 |
| - keyAccess: keyAccessObjects, |
156 |
| - method: { |
157 |
| - algorithm, |
158 |
| - isStreamable: false, |
159 |
| - iv: base64.encode(keyInfo.unwrappedKeyIvBinary.asString()), |
160 |
| - }, |
161 |
| - integrityInformation: { |
162 |
| - rootSignature: { |
163 |
| - alg: 'HS256', |
164 |
| - sig: '', |
165 |
| - }, |
166 |
| - segmentHashAlg: 'GMAC', |
167 |
| - segments: [], |
168 |
| - }, |
169 |
| - policy: policyForManifest, |
170 |
| - }; |
171 |
| - } |
172 |
| -} |
0 commit comments