Errata

Programming .NET Security

Errata for Programming .NET Security

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released.

The following errata were submitted by our customers and have not yet been approved or disproved by the author or editor. They solely represent the opinion of the customer.

Color Key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted by Date submitted
15
3rd paragraphs from the bottom

Executable assembly
...but the types defined in the assembly cannot be used by other...


It looks like this should be removed, as one can use types from executable console app as well as from GUI app.

Andriy  Jul 24, 2009 
Printed Page 22
3rd paragraph

Example on displaying public key from the key pair does not work. An additional step is needed to extract the public key to a file before the display step. Problem occurs with Visual Studio 2008.
Replace:
sn -tp MyKeyPair.snk
With:
sn -p MyKeyPair.snk MyKeyPair.bin
sn -tp MyKeyPair.bin

David Ellison  Apr 03, 2009 
Printed Page 115
middle of page

<FileIOPermission(SecurityAction.Demand, Write = "C:SomeFile.txt">
should read:
<FileIOPermission(SecurityAction.Demand, Write:="C:SomeFile.txt")>

I also happened to notice that there is a similar problem on page 129 with
the colon missing in a VB attribute.

Anonymous   
Printed Page 117
Table 7-3

1. IStackWalk interface should define only the following methods: Assert, Demand, Deny and PermitOnly.

2. ISecurityEncodable has only two methods: FromXml and ToXml. These methods are not a part of the IStackWalk interface.

3. CodeAccessPersmission has the following static methods: RevertAll, RevertAssert, RevertDeny and RevertPermitOnly. They are not a part of the ISecurityEncodable interface. The table does not even show section for static methods of the CodeAccessPermission class.

Alexey  Jun 05, 2010 
Printed Page 125
Second bullet item from the top of the page

"...a FileIOPermission representing the ability to read andsm write to..."

Should be

"...a FileIOPermission representing the ability to read and write to..."

Alexey  Jun 05, 2010 
Printed Page 131
first and second code example

The text describes the way to optionally request full access to the hard drive is to
use:

[assembly: FileIOPermission(PermissionState.Unrestricted)]

and the way to refuse any access to the hard drive is to use:

[assembly: FileIOPermission(PermissionState.Unrestricted)]

The same line of code can't do nearly opposite things

I believe the code should look as follows:

[assembly: FileIOPermission(SecurityAction.RequestOptional, Unrestricted = true)]

and

[assembly: FileIOPermission(SecurityAction.RequestRefuse, Unrestricted = true)]

respectively.

Anonymous   
Printed Page 145
2nd paragraph in "Defining the RadioPerminssion class" section

"RadioPerminssion implements the IUnrestricted interface".
should be:
"...IUnrestrictedPermission interface."

Anonymous   
Printed Page 147
Code Listing

the second constructor looks as follows:

if (actions & (~RadioAction.All)) != 0)
{
// exception throw here
}
else
{
RadioActions = actions
}

this.RadioActions = actions;

I think this is easier to read as follows;

if (actions & (~RadioAction.All)) != 0)
{
// exception throw here
}

this.RadioActions = actions;

Anonymous   
Printed Page 166
2nd paragraph (the "Exclusive" attribute)

The following statement is made for the "Exclusive" attribute;

"Because the final permission set of an assembly or application domain is the union
of the sets of permissions granted..."

I believe that the word "union" should actually be "intersection".

Case in point, page 170, last paragraph where the following statement appears;

"The runtime uses this process to determine the permissions granted by each policy
level and then intersects them to calculate the final code-access permission set for
the assembly."

Also note that Figure 8-7 on page 171 illustrates an intersection as the final grant
set.

Anonymous   
Printed Page 330
C# example at bottom of page

At the bottom of page 329 and top of page 330, it is recommended that an abstract
class Adler32 be defined, but in the following examples (bottom of page 330, middle
of page 331) the abstract class is not used (as it is for the VB example). For
instance, on page 330, the line:

public class Adler32Managed : HashAlgorithm {

should be:

public class Adler32Managed : Adler32 {

or else the 'Defining the Abstract Class' section makes no sense.

Making this change makes the C# sample match the VB sample. All remaining
Adler32Managed samples need to be changed (e.g. page 331, 333).

Anonymous   
Printed Page 452
somewhere in the functions excerpted

private byte[] RestoreOAEPPaddedData(byte[] p_data) {
// create a memory stream to hold the padded data
MemoryStream x_stream = new MemoryStream();

// define K
int x_K = o_algorithm.KeySize/8 -1;

// determine how many complete blocks there are
int x_blocks = p_data.Length / x_K;

// run through and process the blocks blocks
byte[] x_block;
for (int i = 0; i < x_blocks; i++) {
x_block = RestoreSingleOAEPBlock(p_data, i * x_K, x_K, x_K);
x_stream.Write(x_block, 0, x_block.Length);
}

// return the padded data
return x_stream.ToArray();
}

private byte[] RestoreSingleOAEPBlock(byte[] p_data, int p_offset, int p_count, int p_K) {
// b. Separate the encoded message EM into a single octet Y, an octet string maskedSeed
// of length hLen, and an octet string maskedDB of length k &#150;hLen &#150;1 as
// EM = Y || maskedSeed || maskedDB
byte[] x_maskedSeed = new byte[o_lhash.Length];
Array.Copy(p_data, p_offset + 1, x_maskedSeed, 0, o_lhash.Length);
byte[] x_maskedDB = new byte[p_K - o_lhash.Length -1];
Array.Copy(p_data, p_offset + 1 + o_lhash.Length, x_maskedDB, 0, x_maskedDB.Length);
// c. Let seedMask = MGF (maskedDB, hLen).
byte[] x_seedMask = o_mask_generator.GenerateMask(x_maskedDB, o_lhash.Length);
// d. Let seed = maskedSeed XOR seedMask
byte[] x_seed = (new BigInteger(x_maskedSeed) ^ new BigInteger(x_seedMask)).getBytes();
// e. Let dbMask = MGF (seed, k &#150;hLen &#150;1).
byte[] x_dbMask = o_mask_generator.GenerateMask(x_seed, p_K - o_lhash.Length -1);
// f. Let DB = maskedDB XOR dbMask.
byte[] x_DB = (new BigInteger(x_maskedDB) ^ new BigInteger(x_dbMask)).getBytes();
// g. Separate DB into an octet string lHash&#146;of length hLen, a (possibly empty)
// padding string PS consisting of octets with hexadecimal value 0x00, and a message M as
// DB = lHash&#146;|| PS || 0x01 || M .
// If there is no octet with hexadecimal value 0x01 to separate PS from M,
// if lHash does not equal lHash&#146; or if Y is nonzero, output &#38651;ecryption error&#148;and stop.
for (int i = 0; i < o_lhash.Length; i++) {
if (x_DB[i] != o_lhash[i]) {
throw new CryptographicException("Decryption Error");
}
}
if (p_data[0] != 0) {
throw new CryptographicException("Decryption Error");
}
// find the index representing the start of M
int x_index = -1;
for (int i = o_lhash.Length; i < x_DB.Length; i++) {
if (x_DB[i] == 0x01) {
// the next index is the start of M
x_index = i + 1;
break;
} else if (x_DB[i] != (byte)0x00) {
throw new CryptographicException("Decryption Error");
}
}
if (x_index == -1) {
throw new CryptographicException("Decryption Error");
}
// extract and return M
byte[] x_message = new byte[x_DB.Length - x_index];
Array.Copy(x_DB, x_index, x_message, 0, x_message.Length);
return x_message;
}

ComSpex  Jan 22, 2010