Class Crypto
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final StringECDSA over P-256 with SHA-256, and over P-384 with SHA-384.static final Stringstatic final StringThe NIST P-256 curve, forgenerateEcKey(String).static final StringThe NIST P-384 curve, forgenerateEcKey(String).static final intPBKDF2 iterations for a stored password.static final StringRSASSA-PSS over SHA-256 with MGF1-SHA-256 and a 32 byte salt.static final StringRSASSA-PKCS1-v1_5 over SHA-256, SHA-384 and SHA-512: the same bytes for the same key and message, every time.static final Stringstatic final Stringstatic final StringThe digest nameshmac(String, byte[], byte[])andpbkdf2(String, byte[], byte[], int, int)take.static final Stringstatic final Stringstatic final String -
Method Summary
Modifier and TypeMethodDescriptionstatic byte[]aesCbcDecryptBlocks(byte[] key, byte[] iv, byte[] blocks) Decrypts AES-CBC over whole blocks, with no padding: the inverse ofaesCbcEncryptBlocks(byte[], byte[], byte[]).static byte[]aesCbcEncryptBlocks(byte[] key, byte[] iv, byte[] blocks) Encrypts with AES-CBC over whole blocks, with no padding.static byte[]aesGcmDecrypt(byte[] key, byte[] iv, byte[] aad, byte[] sealed) Opens whataesGcmEncrypt(byte[], byte[], byte[], byte[])sealed.static byte[]aesGcmEncrypt(byte[] key, byte[] iv, byte[] aad, byte[] plaintext) AES-GCM.static byte[]ecdh(byte[] privateKey, byte[] peerPublicKey) ECDH key agreement: the x coordinate of the shared point, 32 bytes on P-256 and 48 on P-384, as SEC 1 and every TLS stack define it.static booleanequalsConstantTime(byte[] a, byte[] b) Compares without leaking where two values first differ.static byte[]generateEcKey(String curve) static byte[]generateRsaKey(int bits) A new RSA private key as PKCS#8 DER, with the public exponent 65537.static StringhashPassword(String password) Hashes a password for storage.static byte[]static byte[]hmacSha256(byte[] key, byte[] data) static byte[]md5(byte[] data) MD5, for PostgreSQL's md5 authentication method.static byte[]static byte[]pbkdf2Sha256(byte[] password, byte[] salt, int iterations, int length) PBKDF2-HMAC-SHA-256.static byte[]randomBytes(int length) Cryptographically secure bytes.static byte[]sha1(byte[] data) SHA-1, for the wire protocols that specify it by name: MySQL's mysql_native_password, and the RFC 6455 4.2.2 websocket handshake, where the digest of the client key and a fixed GUID becomes Sec-WebSocket-Accept.static byte[]sha256(byte[] data) static byte[]sha384(byte[] data) SHA-384; null for null.static byte[]sha512(byte[] data) SHA-512; null for null.static byte[]static booleanChecks a signature against a public key in SubjectPublicKeyInfo DER.static booleanverifyPassword(String password, String stored) False for any malformed stored value rather than throwing.
-
Field Details
-
PASSWORD_ITERATIONS
public static final int PASSWORD_ITERATIONSPBKDF2 iterations for a stored password. Deliberately expensive: the cost is paid once per login and multiplied by every guess an attacker makes against a stolen table.- See Also:
-
SHA1
The digest nameshmac(String, byte[], byte[])andpbkdf2(String, byte[], byte[], int, int)take.- See Also:
-
SHA256
- See Also:
-
SHA384
- See Also:
-
SHA512
- See Also:
-
RS256
RSASSA-PKCS1-v1_5 over SHA-256, SHA-384 and SHA-512: the same bytes for the same key and message, every time.- See Also:
-
RS384
- See Also:
-
RS512
- See Also:
-
PS256
RSASSA-PSS over SHA-256 with MGF1-SHA-256 and a 32 byte salt.- See Also:
-
ES256
ECDSA over P-256 with SHA-256, and over P-384 with SHA-384.- See Also:
-
ES384
- See Also:
-
P256
-
P384
-
-
Method Details
-
sha256
public static byte[] sha256(byte[] data) -
sha1
public static byte[] sha1(byte[] data) SHA-1, for the wire protocols that specify it by name: MySQL's mysql_native_password, and the RFC 6455 4.2.2 websocket handshake, where the digest of the client key and a fixed GUID becomes Sec-WebSocket-Accept.
Never for anything this code CHOOSES: passwords go through
hashPassword(String)and tokens throughhmacSha256(byte[], byte[]). Both callers here are standards quoting the algorithm, and in neither is the result standing in for a signature -- the handshake value is a replay guard against caches and proxies, not an authenticator. -
md5
public static byte[] md5(byte[] data) MD5, for PostgreSQL's md5 authentication method. Seesha1(byte[]). -
pbkdf2Sha256
public static byte[] pbkdf2Sha256(byte[] password, byte[] salt, int iterations, int length) throws IOException PBKDF2-HMAC-SHA-256. Exposed because SCRAM-SHA-256 -- how PostgreSQL authenticates by default -- is defined in terms of it with the server's iteration count, whichhashPassword(String)does not let a caller choose.- Throws:
IOException
-
hmacSha256
public static byte[] hmacSha256(byte[] key, byte[] data) -
randomBytes
Cryptographically secure bytes. Throws rather than returning weak ones.- Throws:
IOException
-
equalsConstantTime
public static boolean equalsConstantTime(byte[] a, byte[] b) Compares without leaking where two values first differ. An early exit on the first differing byte lets a MAC be forged one byte at a time. -
hashPassword
Hashes a password for storage. Returns "pbkdf2$iterations$salt$hash" with both binary parts base64url-encoded, so the iteration count travels with the hash and can be raised later without invalidating existing rows.- Throws:
IOException
-
verifyPassword
-
sha384
public static byte[] sha384(byte[] data) SHA-384; null for null. -
sha512
public static byte[] sha512(byte[] data) SHA-512; null for null. -
hmac
HMAC over one ofSHA1,SHA256,SHA384andSHA512. SHA-1 is here for what specifies it by name -- a TOTP secret an authenticator application already holds, Spring's oldest password format -- and not for anything new.- Returns:
- the tag, or null when
keyordatais null - Throws:
IllegalArgumentException- for a digest that is not one of the four
-
pbkdf2
public static byte[] pbkdf2(String digest, byte[] password, byte[] salt, int iterations, int length) throws IOException PBKDF2 over HMAC with one ofSHA1,SHA256,SHA384andSHA512, on the password's bytes as they are given.- Throws:
IOException- when a count is not positive or derivation fails
-
sign
Signs
datawith a private key in PKCS#8 DER, under one ofRS256,RS384,RS512,PS256,ES256andES384.The key has to be of the kind the algorithm is defined over: an RSA key for the first four, a P-256 key for ES256, a P-384 key for ES384. Any other pairing is refused rather than adapted to.
An ECDSA signature is returned as ASN.1 DER, the SEQUENCE of r and s both OpenSSL and the JDK produce. JOSE wants the two numbers side by side instead;
com.codename1.backend.security.crypto.Derconverts.- Throws:
IOException- when the key cannot be read, does not fit the algorithm, or signing fails
-
verify
public static boolean verify(String algorithm, byte[] publicKey, byte[] data, byte[] signature) throws IOException Checks a signature against a public key in SubjectPublicKeyInfo DER. The algorithms and the pairing of key and algorithm are those ofsign(String, byte[], byte[]), and an ECDSA signature is given as ASN.1 DER.- Returns:
- true when
signatureis that key's signature ofdata; false when it is not, whatever is wrong with it - Throws:
IOException- when the question could not be asked: the key cannot be read or does not fit the algorithm. A key that is broken is never reported as a signature that is forged.
-
generateRsaKey
A new RSA private key as PKCS#8 DER, with the public exponent 65537.
For a development profile, so a server that signs tokens starts without a key file. A key made at start-up is gone at the next one, and every token signed with it stops verifying: a deployed server loads its key.
- Parameters:
bits- 2048 to 8192- Throws:
IOException
-
aesGcmEncrypt
public static byte[] aesGcmEncrypt(byte[] key, byte[] iv, byte[] aad, byte[] plaintext) throws IOException AES-GCM. The result is the ciphertext followed by the 16 byte tag.
The nonce must never repeat under one key: 12 bytes from
randomBytes(int)for each call is the ordinary way, stored beside the result.- Parameters:
key- 16, 24 or 32 bytesiv- the nonce; 12 bytes unless a protocol says otherwiseaad- data that is authenticated and not encrypted; null for none- Throws:
IOException
-
aesGcmDecrypt
public static byte[] aesGcmDecrypt(byte[] key, byte[] iv, byte[] aad, byte[] sealed) throws IOException Opens whataesGcmEncrypt(byte[], byte[], byte[], byte[])sealed.- Returns:
- the plaintext, or null when the tag does not match: the key, the nonce, the associated data or the sealed bytes are not the ones it was made with
- Throws:
IOException- when the sizes are not ones AES-GCM has
-
generateEcKey
A new EC private key as PKCS#8 DER, onP256orP384, carrying its public point soDer.publicKeyOfcan give the public half.- Parameters:
curve-"P-256"or"P-384"- Throws:
IOException
-
ecdh
ECDH key agreement: the x coordinate of the shared point, 32 bytes on P-256 and 48 on P-384, as SEC 1 and every TLS stack define it.
The result is key material, not a key: run it through a KDF (HKDF, or the protocol's own) before using it. Both keys must be on the same curve; a public point that is not on its curve is refused.
- Parameters:
privateKey- this side's PKCS#8 EC private keypeerPublicKey- the other side's SubjectPublicKeyInfo- Throws:
IOException- when either key cannot be read, they are on different curves, or the curve is not P-256 or P-384
-
aesCbcEncryptBlocks
Encrypts with AES-CBC over whole blocks, with no padding.
This is the raw mode a format defined over CBC needs -- PKCS#12 and encrypted PKCS#8 -- and nothing more. CBC is not authenticated, so it is deliberately not a general cipher: there is no padding, and so no padding check whose pass or fail an attacker could probe (the padding oracle). A format that pads removes the padding itself, and only after it has verified the data's integrity some other way, as PKCS#12 does with its MAC. Seal new data with
aesGcmEncrypt(byte[], byte[], byte[], byte[]).Encryption and decryption are two methods rather than one with a mode flag, so the rule that matters -- an encrypting IV is random and never repeated under one key -- applies to exactly the method it is about. Decrypting takes whatever IV the data carries, a fixed test vector included.
- Parameters:
key- 16, 24 or 32 bytesiv- 16 bytes, random and never repeated under one key; userandomBytes(int)blocks- a whole number of 16 byte blocks- Throws:
IOException
-
aesCbcDecryptBlocks
Decrypts AES-CBC over whole blocks, with no padding: the inverse ofaesCbcEncryptBlocks(byte[], byte[], byte[]). Nothing is unpadded or checked here; see that method for why.- Parameters:
key- 16, 24 or 32 bytesiv- the 16 byte IV the data was encrypted underblocks- a whole number of 16 byte blocks- Throws:
IOException
-