watchtower/multi: use new blob.BreachKey for enc/dec of justice kits
This commit is contained in:
parent
59bf4857f4
commit
3b51906a78
@ -75,11 +75,6 @@ var (
|
||||
"ciphertext is too small for chacha20poly1305",
|
||||
)
|
||||
|
||||
// ErrKeySize signals that the provided key is improperly sized.
|
||||
ErrKeySize = fmt.Errorf(
|
||||
"chacha20poly1305 key size must be %d bytes", KeySize,
|
||||
)
|
||||
|
||||
// ErrNoCommitToRemoteOutput is returned when trying to retrieve the
|
||||
// commit to-remote output from the blob, though none exists.
|
||||
ErrNoCommitToRemoteOutput = errors.New(
|
||||
@ -223,12 +218,7 @@ func (b *JusticeKit) CommitToRemoteWitnessStack() ([][]byte, error) {
|
||||
//
|
||||
// NOTE: It is the caller's responsibility to ensure that this method is only
|
||||
// called once for a given (nonce, key) pair.
|
||||
func (b *JusticeKit) Encrypt(key []byte, blobType Type) ([]byte, error) {
|
||||
// Fail if the nonce is not 32-bytes.
|
||||
if len(key) != KeySize {
|
||||
return nil, ErrKeySize
|
||||
}
|
||||
|
||||
func (b *JusticeKit) Encrypt(key BreachKey, blobType Type) ([]byte, error) {
|
||||
// Encode the plaintext using the provided version, to obtain the
|
||||
// plaintext bytes.
|
||||
var ptxtBuf bytes.Buffer
|
||||
@ -238,7 +228,7 @@ func (b *JusticeKit) Encrypt(key []byte, blobType Type) ([]byte, error) {
|
||||
}
|
||||
|
||||
// Create a new chacha20poly1305 cipher, using a 32-byte key.
|
||||
cipher, err := chacha20poly1305.NewX(key)
|
||||
cipher, err := chacha20poly1305.NewX(key[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -264,21 +254,17 @@ func (b *JusticeKit) Encrypt(key []byte, blobType Type) ([]byte, error) {
|
||||
// Decrypt unenciphers a blob of justice by decrypting the ciphertext using
|
||||
// chacha20poly1305 with the chosen (nonce, key) pair. The internal plaintext is
|
||||
// then deserialized using the given encoding version.
|
||||
func Decrypt(key, ciphertext []byte, blobType Type) (*JusticeKit, error) {
|
||||
switch {
|
||||
func Decrypt(key BreachKey, ciphertext []byte,
|
||||
blobType Type) (*JusticeKit, error) {
|
||||
|
||||
// Fail if the blob's overall length is less than required for the nonce
|
||||
// and expansion factor.
|
||||
case len(ciphertext) < NonceSize+CiphertextExpansion:
|
||||
if len(ciphertext) < NonceSize+CiphertextExpansion {
|
||||
return nil, ErrCiphertextTooSmall
|
||||
|
||||
// Fail if the key is not 32-bytes.
|
||||
case len(key) != KeySize:
|
||||
return nil, ErrKeySize
|
||||
}
|
||||
|
||||
// Create a new chacha20poly1305 cipher, using a 32-byte key.
|
||||
cipher, err := chacha20poly1305.NewX(key)
|
||||
cipher, err := chacha20poly1305.NewX(key[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -165,8 +165,8 @@ func testBlobJusticeKitEncryptDecrypt(t *testing.T, test descriptorTest) {
|
||||
// Generate a random encryption key for the blob. The key is
|
||||
// sized at 32 byte, as in practice we will be using the remote
|
||||
// party's commitment txid as the key.
|
||||
key := make([]byte, blob.KeySize)
|
||||
_, err := io.ReadFull(rand.Reader, key)
|
||||
var key blob.BreachKey
|
||||
_, err := rand.Read(key[:])
|
||||
if err != nil {
|
||||
t.Fatalf("unable to generate blob encryption key: %v", err)
|
||||
}
|
||||
|
@ -202,13 +202,16 @@ func (l *Lookout) processEpoch(epoch *chainntnfs.BlockEpoch,
|
||||
|
||||
// The decryption key for the state update should be the full
|
||||
// txid of the breaching commitment transaction.
|
||||
commitTxID := commitTx.TxHash()
|
||||
// The decryption key for the state update should be computed as
|
||||
// key = SHA256(txid).
|
||||
breachTxID := commitTx.TxHash()
|
||||
breachKey := blob.NewBreachKeyFromHash(&breachTxID)
|
||||
|
||||
// Now, decrypt the blob of justice that we received in the
|
||||
// state update. This will contain all information required to
|
||||
// sweep the breached commitment outputs.
|
||||
justiceKit, err := blob.Decrypt(
|
||||
commitTxID[:], match.EncryptedBlob,
|
||||
breachKey, match.EncryptedBlob,
|
||||
match.SessionInfo.Policy.BlobType,
|
||||
)
|
||||
if err != nil {
|
||||
|
@ -148,14 +148,17 @@ func TestLookoutBreachMatching(t *testing.T) {
|
||||
CommitToLocalSig: makeArray64(2),
|
||||
}
|
||||
|
||||
// Encrypt the first justice kit under the txid of the first txn.
|
||||
encBlob1, err := blob1.Encrypt(hash1[:], blob.FlagCommitOutputs.Type())
|
||||
key1 := blob.NewBreachKeyFromHash(&hash1)
|
||||
key2 := blob.NewBreachKeyFromHash(&hash2)
|
||||
|
||||
// Encrypt the first justice kit under breach key one.
|
||||
encBlob1, err := blob1.Encrypt(key1, blob.FlagCommitOutputs.Type())
|
||||
if err != nil {
|
||||
t.Fatalf("unable to encrypt sweep detail 1: %v", err)
|
||||
}
|
||||
|
||||
// Encrypt the second justice kit under the txid of the second txn.
|
||||
encBlob2, err := blob2.Encrypt(hash2[:], blob.FlagCommitOutputs.Type())
|
||||
// Encrypt the second justice kit under breach key two.
|
||||
encBlob2, err := blob2.Encrypt(key2, blob.FlagCommitOutputs.Type())
|
||||
if err != nil {
|
||||
t.Fatalf("unable to encrypt sweep detail 2: %v", err)
|
||||
}
|
||||
|
@ -276,22 +276,19 @@ func (t *backupTask) craftSessionPayload(
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the breach hint from the breach transaction id's prefix.
|
||||
breachKey := t.breachInfo.BreachTransaction.TxHash()
|
||||
breachTxID := t.breachInfo.BreachTransaction.TxHash()
|
||||
|
||||
// Compute the breach key as SHA256(txid).
|
||||
hint, key := blob.NewBreachHintAndKeyFromHash(&breachTxID)
|
||||
|
||||
// Then, we'll encrypt the computed justice kit using the full breach
|
||||
// transaction id, which will allow the tower to recover the contents
|
||||
// after the transaction is seen in the chain or mempool.
|
||||
encBlob, err := justiceKit.Encrypt(breachKey[:], t.blobType)
|
||||
encBlob, err := justiceKit.Encrypt(key, t.blobType)
|
||||
if err != nil {
|
||||
return hint, nil, err
|
||||
}
|
||||
|
||||
// Finally, compute the breach hint, taken as the first half of the
|
||||
// breach transactions txid. Once the tower sees the breach transaction
|
||||
// on the network, it can use the full txid to decyrpt the blob.
|
||||
hint = blob.NewBreachHintFromHash(&breachKey)
|
||||
|
||||
return hint, encBlob, nil
|
||||
}
|
||||
|
||||
|
@ -524,7 +524,8 @@ func testBackupTask(t *testing.T, test backupTaskTest) {
|
||||
|
||||
// Decrypt the return blob to obtain the JusticeKit containing its
|
||||
// contents.
|
||||
jKit, err := blob.Decrypt(breachTxID[:], encBlob, policy.BlobType)
|
||||
key := blob.NewBreachKeyFromHash(&breachTxID)
|
||||
jKit, err := blob.Decrypt(key, encBlob, policy.BlobType)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to decrypt blob: %v", err)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user