Bộ chìa khoá

Tink sử dụng Bộ khoá để bật tính năng xoay khoá. Theo cách chính thức, tập hợp khoá là một danh sách không trống1 gồm các khoá, trong đó một khoá được chỉ định là khoá chính (ví dụ: khoá dùng để ký và mã hoá văn bản thô mới). Ngoài ra, các khoá trong một tập hợp khoá sẽ nhận được một mã nhận dạng duy nhất2 và trạng thái khoá cho phép tắt các khoá mà không cần xoá các khoá đó khỏi tập hợp khoá.

Bộ phím là cách chính để người dùng có thể truy cập vào các phím (thông qua lớp KeysetHandle). Điều này đảm bảo rằng mọi người dùng đều có mã để xử lý nhiều phím cùng một lúc. Đối với hầu hết người dùng mật mã, việc xử lý nhiều khoá là nhất thiết: cần có khả năng thay đổi khoá (ví dụ: khoá cũ có thể bị rò rỉ) và hầu như không bao giờ có "chuyển sang khoá tiếp theo" nguyên tử có thể áp dụng cho các máy mà mã chạy và tất cả văn bản đã mã hoá, trên toàn cầu và ngay lập tức. Do đó, người dùng cần viết mã hoạt động khi người dùng chuyển từ khoá này sang khoá tiếp theo.

Ví dụ: AEAD

Hãy xem xét một tập hợp khoá AEAD, chứa nhiều khoá cho nguyên hàm AEAD. Như đã giải thích trước đó, mỗi khoá chỉ định riêng hai hàm: \(\mathrm{Enc}\) và \(\mathrm{Dec}\). Giờ đây, tập hợp khoá cũng chỉ định hai hàm mới: \(\mathrm{Enc}\) và \(\mathrm{Dec}\) - \(\mathrm{Enc}\) chỉ bằng hàm \(\mathrm{Enc}\) của khoá chính của tập hợp khoá, trong khi hàm \(\mathrm{Dec}\) cố gắng giải mã bằng tất cả khoá, đi qua các khoá theo một thứ tự nào đó (xem dưới đây để biết cách Tink cải thiện hiệu suất của việc này).

Điều thú vị là Bộ khoá là khoá đầy đủ: đó là nội dung mô tả đầy đủ về các hàm \(\mathrm{Enc}\) và\(\mathrm{Dec}\) được sử dụng. Điều này có nghĩa là người dùng có thể viết một lớp lấy KeysetHandle làm dữ liệu đầu vào, thể hiện ý tưởng rằng lớp này cần có nội dung mô tả đầy đủ về các đối tượng \(\mathrm{Enc}\) và \(\mathrm{Dec}\) để hoạt động đúng cách. Điều này cho phép người dùng viết các API thông báo rằng: để sử dụng lớp này, bạn cần cung cấp cho tôi nội dung mô tả về một nguyên hàm mã hoá.

Xoay vòng khoá

Hãy xem xét một người dùng Tink, viết một chương trình trước tiên sẽ lấy một tập hợp khoá từ KMS, sau đó tạo một đối tượng AEAD từ tập hợp khoá này và cuối cùng sử dụng đối tượng này để mã hoá và giải mã văn bản đã mã hoá.

Người dùng như vậy sẽ tự động được chuẩn bị cho việc xoay vòng khoá; và chuyển đổi các thuật toán trong trường hợp lựa chọn hiện tại của họ không còn đáp ứng tiêu chuẩn nữa.

Tuy nhiên, bạn phải cẩn thận khi triển khai việc xoay khoá như vậy: Đầu tiên, KMS sẽ thêm một khoá mới vào tập hợp khoá (nhưng chưa đặt khoá đó làm khoá chính). Sau đó, bạn cần triển khai bộ khoá mới cho tất cả tệp nhị phân để mọi tệp nhị phân sử dụng bộ khoá này đều có khoá mới nhất trong bộ khoá. Chỉ khi đó, khoá mới mới được đặt làm khoá chính và tập hợp khoá thu được sẽ được phân phối lại cho tất cả tệp nhị phân bằng cách sử dụng tập hợp khoá.

Giá trị nhận dạng khoá trong văn bản đã mã hoá

Hãy xem xét lại ví dụ về tập hợp khoá AEAD. Nếu làm theo cách đơn giản, việc giải mã văn bản đã mã hoá sẽ yêu cầu Tink cố gắng giải mã bằng tất cả khoá trong Tập hợp khoá, vì không có cách nào để biết khoá nào đã được dùng để mã hoá tập hợp khoá. Điều này có thể gây ra hao tổn hiệu suất lớn.

Do đó, Tink cho phép đặt tiền tố cho văn bản đã mã hoá bằng một chuỗi 5 byte bắt nguồn từ mã nhận dạng. Theo triết lý của "Khoá đầy đủ" ở trên, tiền tố này là một phần của khoá và tất cả văn bản đã mã hoá từng được lấy từ khoá này đều phải có tiền tố này. Khi tạo khoá, người dùng có thể chọn khoá có sử dụng tiền tố như vậy hay không, hoặc sử dụng định dạng văn bản đã mã hoá mà không có tiền tố.

Khi một khoá nằm trong một tập hợp khoá, Tink sẽ tính toán thẻ này từ mã nhận dạng mà khoá có trong tập hợp khoá. Việc mã nhận dạng là duy nhất2 trong một tập hợp khoá ngụ ý rằng các thẻ là duy nhất. Do đó, nếu chỉ sử dụng các khoá được gắn thẻ, thì sẽ không có tổn thất về hiệu suất so với việc giải mã bằng một khoá duy nhất: Tink chỉ cần thử một trong các khoá khi giải mã.

Tuy nhiên, vì thẻ là một phần của khoá, nên điều này cũng ngụ ý rằng khoá chỉ có thể nằm trong một tập hợp khoá nếu khoá đó có một mã nhận dạng cụ thể. Điều này có một số tác động khi mô tả việc triển khai các đối tượng khoá bằng nhiều ngôn ngữ.


  1. Một số phần của Tink vẫn coi Keyset là một tập hợp. Tuy nhiên, bạn nên thay đổi điều này. Lý do là thứ tự nói chung là quan trọng: ví dụ: hãy xem xét vòng đời thông thường của một lượt xoay khoá bằng Aead. Trước tiên, một khoá mới được thêm vào một tập hợp khoá. Khoá này chưa được đặt làm khoá chính, nhưng đang hoạt động. Bộ khoá mới này được triển khai cho tất cả tệp nhị phân. Sau khi tất cả tệp nhị phân biết khoá mới, khoá này sẽ được đặt làm khoá chính (chỉ tại thời điểm này, việc sử dụng khoá này mới an toàn). Trong bước thứ hai này, việc xoay khoá cần biết khoá được thêm gần đây nhất. 

  2. Để tương thích với thư viện nội bộ của Google, Tink cho phép có các tập hợp khoá trong đó các mã nhận dạng được lặp lại. Chúng tôi sẽ xoá tính năng hỗ trợ này trong tương lai.