Re: Securing data to a process principal


You say that you want to lock to a "principal" - but then you say the same
application should be able to decrypt data on another computer. So are you
talking about a DOMAIN user? If not, how do you know if the user has the same
password on multiple computers?
In case of domain, you may use domain objects (just create a random
encryption key first time for the user - and use it later). That would be the

If you need to support independent computers obviously you need some SHARED
secret (key). There are two ways you could do it:

(1) if you assume that the password is always the same, you can derive the
key from it (you already know this part) - but then you need the principal's
password - which should be available when you start the process AS the
principal. One possible way to do this is to have YOUR dll loaded into the
process's address space (the one which handle the EncryptAsProcessPrincipal
function - and INJECT the derived key into the dll's data area. (Again, load
as debug suspended - then you have control over the child process' address
space and can inject data into it.)

(2) IF you can "pre-set" the computers for each principal (user) then you
can use CAPI: you would need to use CAPI containers. Those are by default
protected TO the principal.

Laszlo Elteto
SafeNet, Inc.

"Steve Schuler" wrote:

Hello Dave and Laslo - thanks for your replies

I should probably be more careful in choice of wording. Instead of saying
"Process Identity" (which many will read as PID), I'm now going to say
"Process Principal" to make clear that the granularity I'm after is that any
process or thread running with a security context representing the same
Windows domain Principal can decrypt a secret that was encrypted by a
process or thread running as that same Principal.

To restate my goal, I want something that helps isolate an application's
secrets from other applications on the same shared box. CryptProtectData
with machine context doesn't do that. And CryptProtectData at user context
doesn't work because there's not necessarily an interactive user - it's my
understanding that CryptProtectData actually requires a loaded user profile,
but I'm talking about a non-interactive app doing the decryption - e.g., a
service or an IIS app host. (Is all that's really needed a loaded profile?
If so, could I "manually" load a registry hive and profile to make it work?
I recall seeing code that did that before.) Also, I need the decryption to
work on multiple machines, which are going to be different than the machine
that did the encryption. Would CryptProtectData work in any form in that
case - the docs seem to say no.

To Laslo - I don't need the encryption / decryption to be transparent and
callers will be calling explicit EncryptAsProcessPrincipal or
DecryptAsProcessPrincipal, so I don't need to go down the file driver path.
In any case, I don't think a file driver would address my main requirement,
which is locking things to the calling Principal.

The reason Laslo's #1 is difficult though, even though I have freedom to
specify how apps will call this code, is that I don't want to embed the
pOptionalEntropy (or more broadly, "secret") in the apps. That would just
push the problem one link up the chain - I would now have the issue of
securing pOptionalEntropy. (And yes, obfuscation of a key is the "solution"
that's currently in use in a similar utility.) Instead, my idea is based on
this question: is there already some secret "owned" by the running thread
that has the right granularity? And which the thread can get at? The first
answer is yes: the NT password hash. But the answer to the second question
is seemingly, "not easily". (And yes, the caveat that only Logon Types 2, 4
and 5 will work is OK - my targets for this are IIS app processes, services,
and interactive apps. And I'll deal with the issue of an impersonating
thread running under a network logon by RevertToSelf-ing and then restoring
the impersonation token.)

My idea is basically to use the password hash indirectly, via an NTLM SSPI
operation. It seems like it should work, but I've already spotted one
problem. Namely that I'm not in complete control of whether NTLM or NTLMv2
is done by the NTLM SSP. The introduction of the nonce and timestamp in
NTLMv2 mean that it won't work for what I want (v2 would not generate the
same challenge-response the next time it was called), and it appears that
there's no way to force SSPI to do NTLMv1 if the LMCompatibilityLevel is set
to 3 (and here, if someone knows a way to force this, please chime in).

If anyone can see a better way to accomplish the granularity I need, I'd
appreciate the advice.

Steve Schuler
Safeco Insurance

"lelteto" <lelteto@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
CryptProtectData is good for the actual encryption - but Steve's issue is
to get the PER PROCESS SECRET (pOptionalEntropy).


1. It is not clear from your description what type of data protection
(encryption) you want. If the APPLICATION is calling your code (eg. your
than it's relatively simple - but I guess that you want TRANSPARENT
encryption for any (arbitrary) process without modifying that
code. This is actually very hard: you would need to write a File System
Filter Driver. Don't even think about starting from scratch - would be a
multi-year project in itself (and probably still misses a lot). I would
strongly recommend contacting OSR and buying their toolkit.
( It's not cheap, but would
allow you to do what you want.

One note: You MAY think that instead of a filter driver you can simply
into the file I/O APIs (kernel32, ntdll). That would work for many
applications - and I wrote such hook in the past (part of SSI's /
Rainbow's /
SafeNet's Shell "automatic data protection" feature; also wrote a Win9x
system filter driver for the same). However, this doesn't work for
using memory mapped files - and there are lots of such apps. The only way
know to work transparently with ALL applications is using File System

2. Seems you already have a process which KNOWS the processes you start.
here is what you would need to do: set up a communication between your
starting program and your filter driver. Whenever you start an application
- generate some encryption key from the password
- start it with suspended mode => get process id
- pass the {process_id, key} pair to your filter driver
- maybe you also want to pass path / filename information what to encrypt
(or what NOT to encrypt like executables, dlls, parameter files -
From this point your filter driver can monitor each and every file I/O of
each process your start program REGISTERED - and ignore any other process.

It's not trivial, but certainly doable.

Laszlo Elteto
SafeNet, Inc.

"DaveMo" wrote:

On Mar 3, 8:42 am, "Steve Schuler" <sjs...@xxxxxxxxxx> wrote:
x-posted to and
Hello all -

I've been looking for a way to do this, and I'm hoping someone either
point me at the obvious API that does this that I somehow missed after
searching long and hard, or else can comment on an idea I'll outline
that I think would get me there.

First, here's what I'm trying to do: I want something similar to DPAPI,
with process identity granularity. I'm going to have an administrative
that would take a service ID and password, call LogonUser, and then
call my
encryption API to encrypt data based on something unique to the
context created by LogonUser. Later, I want a process configured to run
that service ID / password identity - and *only* processes running with
identity - to be able to call a decryption API on that data. (As for
why I
want this, it's to provide a "vault" to applications in a shared
environment, where I don't want to require that applications "trust"
other. Machine-level DPAPI is inadequate for this, since any
application can
decrypt another app's secrets.)

So maybe I've missed an obvious way you do this in Windows, and someone
point me at the right API ... but if not, here's my idea:

An obvious secret associated with the process' identity is the password
hash, but how to get at it - there's no API that I can find that would
me do that. (Of course there are hacker tools that do this using kernel
code, but I don't want anything so messy.) Now here's the idea: I do
client and server sides of the NTLM challenge / response using SSPI (I
code that does this already from something else), but I don't really do
server side that would be generating a random challenge. Instead I feed
constant pre-baked challenge packet to the second call to
InitializeSecurityContext, so that I get the same challenge response
every time, but one which still depends uniquely on the caller's
context. That challenge response could then be used in a CryptDeriveKey
to get the actual reversible encryption key.

I'd appreciate any comments. (Weakenesses, reasons it won't work,
approaches, etc.)

Steve Schuler
Safeco Insurance

Hello Steve,

CryptProtectData() should be exactly what you are looking for.