Title: An example using the SUN provider
1An example using the SUN provider
- The provider SUN is supplied in Java 2SDK.
- SUN provides both
- an implementation of the NIST Digital Signature
Algorithm (DSA), and - an implementation of the MD5 and NIST SHA-1
message digest algorithms. - Class MessageDigest
- looking at code that generates a message digest
from a message. -
- MessageDigest messagedigest MessageDigest.
getInstance("SHA")MessageDigest messagedigest
MessageDigest.getInstance("SHA", "SUN") - getInstance() method can be used in two different
way. - The first requires only the algorithm to be
specified. - The second requires both the algorithm and the
provider to be specified. - Both return an instance of a class that
implements the SHA algorithm.
2- Next, we pass the message through the
message-digest generator. - int n 0 byte
rgb new byte 1000 while
((n inputstreamMessage.read(rgb)) gt -1)
messagedigest.update(rgb, 0, n)
- This code works well for large messages of
unknown length. - The update() method also accepts a single byte as
an argument for messages of a few bytes in
length, and - a byte array for messages of a fixed or
predictable size. -
- The final step involves generating the message
digest itself. - rgb messagedigest.digest
() - The resulting digest is encoded in an array of
bytes.
3Message Digest Algorithm
- A message digest algorithm computes a (typically
shorter) fixed-size string from a message called
the message digest (also known as a digital
fingerprint). - Any change to the original message will result
in a different message digest, providing a way to
verify the integrity (that is, check the
fingerprint) of the original message.
The message digest algorithm creates a message
digest from a message.
4- The Complete Source Code for a program that
Generates a Message
5- import java.security.MessageDigest
- import java.security.NoSuchAlgorithmException
- import java.io.InputStream
- import java.io.OutputStream
- import java.io.FileInputStream
- import java.io.FileOutputStream
- import java.io.IOException
- Public class MessageDigestGenerator
-
- public void generateMessageDigest(
InputStream inputstreamMessage, - OutputStream outputstreamMessageDigest)
- throws NoSuchAlgorithmException,
- IOException
-
- MessageDigest messagedigest
MessageDigest.getInstance("SHA") - int n 0
- byte rgb new byte 1000
- while ((n inputstreamMessage.re
ad(rgb)) gt -1)
6- rgb messagedigest.digest()
- outputstreamMessageDigest.write(rgb)
-
- public static void main(String
rgstring) -
- try
-
- FileInputStream fileinputstream new
FileInputStream(rgstring0) - FileOutputStream fileoutputstream new
FileOutputStream(rgstring1) - new MessageDigestGenerator().
generateMessageDigest (fileinputstream, -
fileoutputstream) - fileinputstream.close()
- fileoutputstream.close()
-
7Classes InputStream OutputStream
- public abstract class InputStream extends Object
- This abstract class is the superclass of all
classes representing an input stream of bytes. - Applications that need to define a subclass of
InputStream must always provide a method that
returns the next byte of input. - public abstract class OutputStream extends Object
- This abstract class is the superclass of all
classes representing an output stream of bytes. - An output stream accepts output bytes and sends
them to some sink. - Applications that need to define a subclass of
OutputStream must always provide at least a
method that writes one byte of output.
8InputStream class read method detailed
- int read (byte b)
- Reads some number of bytes from the input stream
and stores them into the buffer array b. - The number of bytes actually read is returned as
an integer. - This method blocks until input data is available,
end of file is detected, or an exception is
thrown. - If b is null, a NullPointerException is thrown
- .If the length of b is zero, then no bytes are
read and 0 is returned - otherwise, there is an attempt to read at least
one byte. - If no byte is available because the stream is at
end of file, the value -1 is returned - otherwise, at least one byte is read and stored
into b. - Parameter b - the buffer into which the data is
read. - Returns the total number of bytes read into the
buffer, or -1 is there is no more data because
the end of the stream has been reached. - Throws IOException - if an I/O error occurs.
- NullPointerException- if b is null.
9OutputStream class write method detailed
- void write (byte b)
- Writes b.length bytes from the specified byte
array to this output stream. - The general contract for write(b) is that it
should have exactly the same effect as the call - write(b, 0, b.length).
- Parameters b - the data.
- Throws IOException if an I/O error occurs.
- Class IOException
- java.lang.Object
- java.lang.Throwable
- java.lang.Exception
- java.io.IOException
10Class FileInputStream
- public class FileInputStream extends
-
InputStream - A FileInputStream obtains input bytes from a file
in a file system. - What files are available depends on the host
environment. - FileInputStream is meant for reading streams of
raw bytes such as image data. - For reading streams of characters, consider using
FileReader.
11 FileInputStream Constructor
- public FileInputStream(String name) throws
-
FileNotFoundException - Creates a FileInputStream by opening a connection
to an actual file, the file named by the path
name name in the file system. - A new FileDescriptor object is created to
represent this file connection. - First, if there is a security manager, its
checkRead method is called with the name argument
as its argument. - If the named file does not exist, is a directory
rather than a regular file, or for some other
reason cannot be opened for reading then a
FileNotFoundException is thrown.
12Class FileOutputStream
- public class FileOutputStream extends
OutputStream - A file output stream is an output stream for
writing data to a File or to a FileDescriptor. - Whether or not a file is available or may be
created depends upon the underlying platform. - Some platforms, in particular, allow a file to be
opened for writing by only one FileOutputStream
(or other file-writing object) at a time. - In such situations the constructors in this class
will fail if the file involved is already open. - FileOutputStream is meant for writing streams of
raw bytes such as image data. - For writing streams of characters, consider using
FileWriter.
13FileOutputStream Constructor
- public FileOutputStream(String name) throws
-
FileNotFoundException - Creates an output file stream to write to the
file with the specified name. - A new FileDescriptor object is created to
represent this file connection. - First, if there is a security manager, its
checkWrite method is called with name as its
argument. - Parameters name - the system-dependent filename
- Throws FileNotFoundException
- if the file exists but is a directory rather
than a regular file, - if the file does not exist but cannot be
created, or - if the file cannot be opened for any other
reason - SecurityException
- if a security manager exists and its checkWrite
method denies write access to the file.
14 Key in Cryptographic Circles
- A key is a piece of information used to encrypt
and/or decrypt information - There are two types of key-based cryptography
- secret-key and public-key.
- Secret-key cryptography uses a single key that
both encrypts and decrypts the information to be
protected. - Both the sender and the receiver must share the
secret-key. - Secret-key cryptography is also known as
symmetric cryptography. - Public-key cryptography uses two keys
- a public key and a private key.
- One key decrypts information encrypted with the
other. - Only the private key must be protected.
- Public key cryptography is used for
authentication.
15 Class KeyPairGenerator
- To generate a digital signature (and encrypt
data), we need keys. - Key generation, in its algorithm-independent
form, is not substantially similar to creating
and using a message digest. - KeyPairGenerator keypairgenerator
- KeyPairGenerator.getInstance
("DSA") - this code creates an instance of a class that
generates DSA-compatible keys. - A second (if necessary) argument specifies the
provider.
16- After a key-pair generator instance is created,
it must be initialized. - We can initialize key-pair generators in one of
two ways - algorithm-independent or
algorithm-dependent. - Which method we use depends on the amount of
control we want over the final result. - keypairgenerator.initialize(1024, new
SecureRandom()) - Keys based on different algorithms differ in how
they're generated, but they have one parameter in
common -- the key's strength. - Strength is a relative term that corresponds
roughly to how hard the key will be to "break." - If we use the algorithm-independent initializer,
we can specify only the strength -- any
algorithm-dependent values assume reasonable
defaults. -
17- DSAKeyPairGenerator dsakeypairgenerator
(DSAKeyPairGenerator)
keypairgenerator DSAParams dsaparams new
DSAParams() private BigInteger p
BigInteger(...) private BigInteger q
BigInteger(...) private BigInteger g
BigInteger(...) public BigInteger
getP() return p
public BigInteger getQ()
return q
public BigInteger getG()
return g
dsakeypairgenerator.initialize(dsaparams, new
SecureRandom())
18- While the defaults are usually good enough, if we
need more control, it is available. - Let's assume we used the engine to create a
generator of DSA-compatible keys, as in the code
above. - The engine loaded and instantiated an instance of
a class that implements the DSAKeyPairGenerator
interface. - If we cast the generic key-pair generator we
received to DSAKeyPairGenerator, we then gain
access to the algorithm-dependent method of
initialization. - To initialize a DSA key-pair generator, we need
three values - the prime P, the subprime Q, and
the base G. - These values are captured in an inner class
instance that is passed to the initialize()
method. - The SecureRandom class provides a secure source
of random numbers used in the key-pair
generation. - return keypairgenerator.generateKeyPai
r() - The final step involves generating the key pair
itself.
19- The Complete Source Code for a program that
Generates a Key Pair.
20- import java.security.Key
- import java.security.KeyPair
- import java.security.KeyPairGenerator
- import java.security.NoSuchAlgorithmException
- import java.security.SecureRandom
- import java.io.File
- import java.io.InputStream
- import java.io.OutputStream
- import java.io.FileInputStream
- import java.io.FileOutputStream
- import java.io.ObjectInputStream
- import java.io.ObjectOutputStream
- import java.io.IOException
- public class KeyTools
- public static void writeToFile(Key key,
File file) throws IOException - FileOutputStream fileoutputstream new
FileOutputStream(file) - ObjectOutputStream objectoutputstream new
-
ObjectOutputStream(fileoutputstream)
objectoutputstream.writeObject(key) - objectoutputstream.close()
21- public static Key readFromFile(File file)
- throws ClassNotFoundException,
- IOException
-
- FileInputStream fileinputstream new
FileInputStream(file) - ObjectInputStream objectinputstream new
-
ObjectInputStream (fileinputstream) - Key key (Key)objectinputstream.readObject(
) - objectinputstream.close()
- return key
-
- public static void writeToStream(Key key,
OutputStream outputstream) -
throws IOException -
- new ObjectOutputStream (outputstream)
.writeObject(key) -
- public static Key readFromStream
(InputStream inputstream) - throws
ClassNotFoundException,IOException -
22- public static KeyPair generateKeyPair()
throws NoSuchAlgorithmException -
- KeyPairGenerator keypairgenerator
KeyPairGenerator.getInstance("DSA") - keypairgenerator.initialize(1024, new
SecureRandom()) - return
- keypairgenerator.generateKeyPair()
-
- public static void main(String
rgstring) -
- try
-
- File filePublic new File(rgstring0)
- File filePrivate new
File(rgstring1) - KeyPair keypair generateKeyPair()
- writeToFile(keypair.getPublic(),
filePublic) - writeToFile(keypair.getPrivate(),
filePrivate) -
- catch (Exception ex)
-
23Class ObjectOutputStream
- An ObjectOutputStream writes primitive data types
and graphs of Java objects to an OutputStream. -
- public class ObjectOutputStream extends
OutputStream - For example to write an object that can be read
by the example in ObjectInputStream - FileOutputStream fos new FileOutputStream("t.tmp
") - ObjectOutputStream oos new ObjectOutputStream(fo
s) - oos.writeInt(12345)
- oos.writeObject ("Today")
- oos.writeObject(new Date())
- oos.close()
24- Only objects that support the java.io.Serializable
interface can be written to streams. - The class of each serializable object is encoded
including the class name and signature of the
class, the values of the object's fields and
arrays, and the closure of any other objects
referenced from the initial objects. - The method writeObject is used to write an object
to the stream. - Any object, including Strings and arrays, is
written with writeObject. - Multiple objects or primitives can be written to
the stream. - The objects must be read back from the
corresponding ObjectInputstream with the same
types and in the same order as they were written
25 26- A digital signature is also generated from a
message. - It differs from a message digest because the
private key of the message generator is
incorporated into the computation. - The result is a message that has been "signed" by
the one who holds the private key. - The computation is carried out in such a way
that anyone can use the message generator's
public key to verify that the entity signed it. - A good digital signature algorithm guarantees
that the digital signature can't be forged
(assuming the private key is secret), - that the signature is good for only the message
from which it was generated, - that the message cannot be changed without
invalidating the signature - that the message's authenticity can be verified.
27The digital signature algorithm creates a digital
signature from a message and a private key.
28Class Signature
- The creation and use of an instance of the
Signature class is also similiar to the two
previous examples. - The differences lie in how the instance is used
either - to sign or
- to verify a message.
- Signature signature
Signature.getInstance ("DSA") - Firstly, we use the engine to get an instance of
the appropriate type. - What we do next depends on whether or not we are
signing or verifying a message. -
signature.initSign (privatekey) - In order to sign a message, we must first
initialize the signature instance with the
private key of the entity that is signing the
message. -
signature.initVerify(publickey) - In order to verify a message, we must initialize
the signature instance with the public key of the
entity that claims it signed the message.
29- int n 0 byte rgb new byte
1000 while ((n inputstreamMessage.read(rgb
)) gt -1) signature.update(rgb, 0,
n) - Next, regardless of whether or not we are signing
or verifying, we must pass the message through
the signature generator. - This process is similiar to the earlier example
of generating a message digest. - The final step consists of generating the
signature or verifying a signature. - rgb
signature.sign() - If we are signing a message, the sign() method
returns the signature. - signature.verify
(rgbSignature) - If we are verifying the signature previously
generated from a message, - we must use the verify() method.
- It takes as a parameter the previously generated
signature and determines whether or not it is
still valid.
30The Complete Source Code for a program that Signs
a Message
31- import java.security.Signature
- import java.security.PrivateKey
- import java.security.NoSuchAlgorithmException
- import java.security.InvalidKeyException
- import java.security.SignatureException
- import java.io.File
- import java.io.InputStream
- import java.io.FileInputStream
- import java.io.IOException
- public class Sign
-
- public static byte generateSignature
(PrivateKey privatekey, InputStream -
inputstreamMessage) - throws NoSuchAlgorithmException,
nvalidKeyException, SignatureException, -
IOException -
- Signature signature Signature.getInstance(
"DSA") - signature.initSign (privatekey)
- int n 0
32- public static void main(String rgstring)
-
- try
- File filePrivate new
File(rgstring0) - File fileMessage new
File(rgstring1) - File fileSignature new
File(rgstring2) - PrivateKey privatekey
(PrivateKey)KeyTools.readFromFile(filePrivate) - FileInputStream fileinputstream new
FileInputStream(fileMessage) - byte rgb generateSignature(privateke
y, fileinputstream) - fileinputstream.close()
- SignatureTools.writeToFile(rgb,
fileSignature) -
- catch (Exception ex)
-
- ex.printStackTrace()
-
-
-
33- The Complete Source Code for a program that
Verifies a Message.
34- import java.security.Signature
- import java.security.PublicKey
- import java.security.NoSuchAlgorithmException
- import java.security.InvalidKeyException
- import java.security.SignatureException
- import java.io.File
- import java.io.InputStream
- import java.io.IOException
- import java.io.OutputStream
- import java.io.FileInputStream
- import java.io.FileOutputStream
- public class Verify
- public static boolean verifySignature
(PublicKey publickey, - Input Stream inputstreamMessage,
byte rgbSignature) - throws NoSuchAlgorithmException,
InvalidKeyException, - SignatureException,IOException
-
- Signature signature Signature.getInstance("DSA")
- signature.initVerify(publickey)
35- public static void main(String
rgstring) - try
-
- File filePublic new File(rgstring0)
- File fileMessage new
File(rgstring1) - File fileSignature new
File(rgstring2) - PublicKey publickey (PublicKey)KeyTools
.readFromFile(filePublic) - FileInputStream fileinputstream new
FileInputStream(fileMessage) - byte rgb SignatureTools.readFromFile
(fileSignature) - if (verifySignature (publickey,
fileinputstream, rgb)) -
- System.out.println ("true")
- else
-
- System.out.println ("false")
-
- fileinputstream.close()
36- The JCA conveniently hides all the low-level
implementation and algorithm-specific details,
allowing you to work at a higher, more abstract
level. - Of course, one of the risks of such an abstract
approach is the increased likelihood that we
won't recognize erroneous output resulting from
bugs. - Given the role of cryptography, this can be a
significant problem. - Consider the "off-by-one" bug in the update line
below - int n 0 byte rgb new byte
1000 while ((n inputstreamMessage.read(rgb
)) gt -1) messagedigest.update(rgb, 0,
n - 1)
37- SUN version 1.5 sun.security.provider.Sun
- SunRsaSign version 1.5
- sun.security.rsa.SunRs
aSign - SunJSSE version 1.5
- com.sun.net.ssl.internal.
ssl.Provider - SunJCE version 1.5
- com.sun.crypto.provider.S
unJCE - SunJGSS version 1.0
- sun.security.jgss.SunPro
vider - SunSASL version 1.5
- com.sun.security.sasl.
Provider - SunDeploy-MSCrypto 1.5 version
- com.sun.deploy.security.MSCryptoProvid
er
38- package sun.security.provider
- import java.io.
- import java.util. import java.security.
- public final class Sun extends Provider
- private static final String INFO "SUN "
"(DSA key/parameter generation DSA signing "
"SHA-1, MD5 digests SecureRandom X.509
certificates JKS keystore)" - public Sun() / We are the SUN provider /
- super("SUN", 1.2, INFO)
- AccessController.doPrivileged(new
java.security.PrivilegedAction() - public Object run() / Signature engines
/ - put("Signature.SHA1withDSA", "sun.security.provid
er.DSA") - put("Alg.Alias.Signature.DSA", "SHA1withDSA")
- put("Alg.Alias.Signature.DSS", "SHA1withDSA")
- put("Alg.Alias. Signature. SHA/DSA",
"SHA1withDSA") - put("Alg.Alias.Signature.SHA-1/DSA",
"SHA1withDSA") - put("Alg.Alias.Signature.SHA1/DSA",
"SHA1withDSA") - put("Alg.Alias.Signature.SHAwithDSA",
"SHA1withDSA") - put("Alg.Alias.Signature.DSAWithSHA1",
"SHA1withDSA") - put("Alg.Alias.Signature.OID.1.2.840.10040.4.3",
"SHA1withDSA") - put("Alg.Alias.Signature.1.2.840.10040.4.3",
"SHA1withDSA")
39- Key Pair Generator engines /
- put( KeyPairGenerator.DSA", "sun.security.provide
r.DSAKeyPairGenerator") - put("Alg.Alias.KeyPairGenerator.OID.1.2.840.10040.
4.1", "DSA") - put("Alg.Alias.KeyPairGenerator.1.2.840.10040.4.1"
, "DSA") - put("Alg.Alias.KeyPairGenerator.1.3.14.3.2.12",
"DSA") - / Digest engines /
- put("MessageDigest.MD5", "sun.security.provider.M
D5") - put( "MessageDigest.SHA", "sun.security.provider.
SHA") - put("Alg.Alias.MessageDigest.SHA-1", "SHA")
- put("Alg.Alias.MessageDigest.SHA1", "SHA")
- / Algorithm Parameter Generator engines /
- put ("AlgorithmParameterGenerator.DSA",
- "sun.security.provider.DSAParam
eterGenerator") - / Algorithm Parameter engines /
- put("AlgorithmParameters.DSA", "sun.security.provi
der.DSAParameters") - put("Alg.Alias.AlgorithmParameters.1.3.14.3.2.12",
"DSA") - put("Alg.Alias.AlgorithmParameters.1.2.840.10040.4
.1", "DSA") - / Key factories /
- put( KeyFactory.DSA", "sun.security.provider.DSAK
eyFactory")
40- / SecureRandom /
- put("SecureRandom.SHA1PRNG", "sun.security.provide
r.SecureRandom") - / Certificates /
- put("CertificateFactory.X509", "sun.security.provi
der.X509Factory") - put("Alg.Alias.CertificateFactory.X.509",
"X509") - / KeyStore /
- put ("KeyStore. JKS", "sun.security.provider.Java
KeyStore") - / KeySize /
- put("Signature.SHA1withDSA KeySize", "1024")
- put("KeyPairGenerator.DSA KeySize", "1024")
put("AlgorithmParameterGenerator.DSA KeySize",
"1024") - / Implementation type software or hardware
/ - put("Signature.SHA1withDSA ImplementedIn",
"Software") - put("KeyPairGenerator.DSA ImplementedIn",
"Software") - put("MessageDigest.MD5 ImplementedIn",
"Software") - put("MessageDigest.SHA ImplementedIn",
"Software") - put("AlgorithmParameterGenerator.DSA
ImplementedIn", "Software") - put("AlgorithmParameters.DSA ImplementedIn",
"Software") - put("KeyFactory.DSA ImplementedIn", "Software")
- put("SecureRandom.SHA1PRNG ImplementedIn",
"Software")
41Example Java Security Providers
- The following Java2 applet enumerates all the
Java Security Providers available to the j2re and
their associated properties and values. - These property values specify the
engine.algorithms and the classes that implement
them, as well as other properties. - The public method of the applet is accessed by a
scripted call to the method from JavaScript. - The method returns the data in a formatted table
string. - A JavaScript function embeds the table of
results into a simple html page in another
scripted window.
42- import java.io.
- import java.util.
- import java.awt.
- import java.security.
- public class SecProviders extends
java.applet.Applet - public void init() // end init()
- public String getSecurityProviders()
- StringBuffer strbuff new
StringBuffer(10000) - //typical size of buffer to hold html string
output - try
- Provider p
Security.getProviders() - strbuff.append("lttable
border1 cellpadding 3gt") - for (int i 0 i lt p.length i)
- strbuff.append("lttrgtlttd bgcolor blue colspan
2gtltfont size1 coloryellowgtltbgt" pi
"nbsp nbsp nbsp nbsp" - pi. getClass(). getName()
"lt/bgtlt/fontgtlt/trgt\r\n") -
43- for (Enumeration e pi.keys()
-
e.hasMoreElements()) - String key (String)
e.nextElement() - strbuff.append("lttrgtlttdgt" key "lt/tdgtlttdgt"
pi.getProperty(key) "lt/tdgtlt/trgt\r\n") -
-
- strbuff.append("lt/tablegt\r\n"
) - return
strbuff.toString() -
- catch (Exception e)
- return e.toString()
-
-
-
44The subclasses of the Provider class
- For each service implemented by the provider,
there must be a property whose name is the type
of service - Signature.algName one or more spaces attrName
- MessageDigest.algName one or more spaces
attrName - KeyPairGenerator.algName one/more spaces
attrName - SecureRandom.algName one /spaces attrName
- KeyFactory.algName one / spaces attrName
- CertificateFactory.certType one or more spaces
attrName - KeyStore.storeType one or more spaces attrName
- AlgorithmParameterGenerator.algName one /
spaces attrName - AlgorithmParameters.algName one / more spaces
attrName
45Java Security Provider Examples
- The default provider "SUN" implements the
SHA1withDSA Digital Signature Algorithm in
software. - In the master class for the provider "SUN", it
sets the "Signature.SHA1withDSA ImplementedIn" to
have the value "Software" via the following - put ("Signature.SHA1withDSA ImplementedIn",
"Software") - The default provider "SUN" implements the
Digital Signature Algorithm (whose standard name
is "SHA1withDSA") in a class named DSA in the
sun.security.provider package. - Its subclass of Provider sets the
Signature.SHA1withDSA property to have the value
"sun.security.provider.DSA" via the following - put("Signature.SHA1withDSA", "sun.security.provide
r.DSA")
46getProvidersmethod
- public static Provider getProviders()
- Returns an array containing all the installed
providers. The order of the providers in the
array is their preference order. - Returns an array of all the installed providers.
47getProvidermethod
- public static Provider getProvider(String name)
- Returns the provider installed with the specified
name, if any. - Returns null if no provider with the specified
name is installed. - Parameters name - the name of the provider to
get. - Returns he provider of the specified name.
48 get Providers method
- public static Provider getProviders (Map
filter) - Returns an array containing all installed
providers that satisfy the specified selection
criteria, or - Returns null if no such providers have been
installed. - The returned providers are ordered according to
their preference order - Parameters filter - the criteria for selecting
providers. The filter is case-insensitive. - Returns all the installed providers that
satisfy the selection criteria, or null if no
such providers have been installed. - Throws InvalidParameterException - if the
filter is not in the required format - The selection criteria are represented by a map.
- Each map entry represents a selection criterion.
- A provider is selected iff it satisfies all
selection criteria.
49The key entry
- The key for any entry in such a map must be in
one of the following two formats - ltcrypto_servicegt.ltalgorithm_or
_typegt - MessageDigest.SHA-384 , MessageDigest.MD5 ,
- The cryptographic service name must not contain
any dots. - The value associated with the key must be an
empty string. - A provider satisfies this selection criterion
iff the provider implements the specified
algorithm or type for the specified cryptographic
service. - ltcrypto_servicegt.ltalgorithm_or_typegt
ltattribute_namegt - Provider.id className , Provider.id version ,
KeyStore.JKS ImplementedIn , - MessageDigest.SHA ImplementedIn ,
KeyFactory.DSA ImplementedIn - The cryptographic service name must not contain
any dots. - The value associated with the key must be a
non-empty string. - A provider satisfies this selection criterion iff
the provider implements the specified algorithm
or type for the specified cryptographic service
and its implementation meets the constraint
expressed by the specified attribute name/value
pair.