Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Value Sealing and Encryption #15

Open
dmbarbour opened this issue Aug 14, 2014 · 6 comments
Open

Value Sealing and Encryption #15

dmbarbour opened this issue Aug 14, 2014 · 6 comments

Comments

@dmbarbour
Copy link
Owner

At the moment, I have {:u} as type a → Sealed :u a for discretionary sealers, which serves a role similar to newtype in Haskell languages (i.e. you cannot accidentally use the value without correctly unsealing it, and we can test this at typecheck time typecheck this).

But long term, I plan to have an secure API for acquiring fresh sealer/unsealer pairs. I need to progress further on this, though the need isn't pressing at the moment (it can wait until I'm really moving forward on distributed programming).

I must protect ABC's spatial idempotence property. Thus, I'll need either to linearize the sealer/unsealer pair generator, or to pass a linear 'uniqueness source' as an argument. I can still make a few decisions here, and I should review my ideas for source-stable uniqueness, i.e. 'splitting' the generator should involve a uniquely named child to ensure stable outputs.

Anyhow, my idea is that sealed values are not encrypted until serialization, i.e. such that if we seal then unseal a value without leaving a local machine we also never go through the encryption step. Also, 'discretionary sealed' values are never encrypted (i.e. they'll be quoted as #42[{:foo}]$ or similar, even when sending the block to a remote system.

The encrypted values will have a format something closer to: "binaryCipherText\n~[{$!hint}] (cf. #12 for binary encoding). I must to decide on a standard naming convention, slightly different from true sealers, but $ isn't a bad prefix. We could use $: for the sealer, $. for the unsealer, and $! for the sealed encrypted value.

What is the cipher text? In this case, it should simply be a representation of more ABC, likely compressed using the exact same algorithm as ABC resources, of type 1→Value. So the unsealer will decrypt this, then compute the value.

@dmbarbour
Copy link
Owner Author

Of potential interest is some ability to apply homomorphic encryption, or at least a weaker ability to specify transformations for a sealed value without actually unsealing it (and without sharing the seal or unseal capabilities). I can think of a few potential approaches to represent this. It may be worth leaving a 'hole' in the design for such extensions, even if I don't get around to it for some time.

@dmbarbour
Copy link
Owner Author

For secure sealer/unsealer pairs, an ECC public key mechanism might work pretty well. It can allow much smaller key sizes compared to RSA (e.g. 384 bits, same size as a resource ID). I'll just need to beware of the dubious algorithms promoted by the NSA, e.g. looking instead into those used by Bitcoin and Namecoin.

@dmbarbour
Copy link
Owner Author

Need to remember: sealed values must use a block type, to preserve substructural properties. Maybe model a sealed value as a block to which you pass the key?

    sealed value :: [Key → Value]

Internally, the block could use cipher-text and a common decryption capability. A key could itself be modeled as a special, sealed value that can only be provided by an unsealer capability (i.e. not just arbitrary text).

For debugging purposes, we might want to further indicate this is a sealed value with some sort of 'brand' or 'hint' provided by the developer. For key-chain purposes, a developer may also wish to explicitly couple sealer or unsealer capabilities with other metadata. But having a block at the very bottom seems 'right' for modeling sealed values.

@dmbarbour
Copy link
Owner Author

I can't directly use a block, e.g. [Key → a], because anyone could then manipulate the value just by composing with the block, which would harm integrity of sealed data. I suppose even storing the data within a block would be a bad idea, because the same attack could be applied through reflection on the ABC stream. It seems I'll need to expose the cipher text more directly to the unseal capability.

But I do need a block, still, to at least attribute the affine and relevance properties, and it does seem reasonable to wrap the cipher text within the block to make it a little more opaque. I could perhaps simply use [1→CipherText] as the encrypted sealed value type.

dmbarbour added a commit that referenced this issue Aug 30, 2014
Switched to 128/256 bits lookup and encryption for ABC resources (#20).

closes #20
@dmbarbour
Copy link
Owner Author

Okay, last night I came up with a satisfying design for secure value sealing, using symbol '$' for secure sealers:

    {:format$encryptionKey}            cryptographic sealer
    {.format$decryptionKey}            cryptographic unsealer
    {$format}                          indicates sealed value

Serializations:

    ["cipherText\n~c]f{$format}        cryptographically sealed affine value
    #42 [{:foo}]$                      for contrast, a discretionary sealed value

Here, the cipherText is basically the same as an ABC resource - compressed and encrypted, though the encryption in this case depends on the format. To regenerate the value, we'll decrypt and decompress the cipherText, then run it. It will have type 1→Value.

The cipher text is wrapped in a block mostly so we can preserve substructural types of the sealed values: affine, relevant, etc. It is then marked as sealed with {$format} to prevent manipulation before it is unsealed.

The format might be something like 'ecc.secp256k1' (to indicate the same, weak Elliptic curve cryptography used in Bitcoin). The default format string would be left blank. Most likely, we'll settle on just one common, default format.

Elliptic curve cryptography is promising in general because it allows asymmetric encryption with relatively small keys (twice the size compared to symmetric key encryption). However, it seems that a lot of ECC curves are 'weak', including secp256k1, and it seems difficult to know whether a curve is intentionally weak as a honeypot. Using Bitcoin's exact curve is tempting, though, because I'd at least hear about it if broken. But there are other suggestions. Cf. safe curves

@dmbarbour
Copy link
Owner Author

In case of ECC encryption, it may be useful to apply 'point compression' on the public key. This takes a bit more time to recover the key, but less time to serialize it. And the key would be easily cached. OTOH, might be better just to send the whole key, if the savings would be marginal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant