jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/DkCrypto.java
author chegar
Mon, 14 Dec 2015 19:24:33 +0000
changeset 34687 d302ed125dc9
parent 27957 24b4e6082f19
permissions -rw-r--r--
8144995: Move sun.misc.HexDumpEncoder to sun.security.util Reviewed-by: psandoz, mchung
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     2
 * Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * Copyright (C) 1998 by the FundsXpress, INC.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     7
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * All rights reserved.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     9
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 * Export of this software from the United States of America may require
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * a specific license from the United States Government.  It is the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * responsibility of any person or organization contemplating export to
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * obtain such a license before exporting.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 * distribute this software and its documentation for any purpose and
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * without fee is hereby granted, provided that the above copyright
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * notice appear in all copies and that both that copyright notice and
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * this permission notice appear in supporting documentation, and that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 * the name of FundsXpress. not be used in advertising or publicity pertaining
90ce3da70b43 Initial load
duke
parents:
diff changeset
    21
 * to distribution of the software without specific, written prior
90ce3da70b43 Initial load
duke
parents:
diff changeset
    22
 * permission.  FundsXpress makes no representations about the suitability of
90ce3da70b43 Initial load
duke
parents:
diff changeset
    23
 * this software for any purpose.  It is provided "as is" without express
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 * or implied warranty.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
package sun.security.krb5.internal.crypto.dk;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
import javax.crypto.Cipher;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
import javax.crypto.Mac;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
import java.security.GeneralSecurityException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
import java.io.UnsupportedEncodingException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
import java.util.Arrays;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
import java.io.ByteArrayInputStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
import java.io.ByteArrayOutputStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
import java.nio.charset.Charset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
import java.nio.CharBuffer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
import java.nio.ByteBuffer;
34687
d302ed125dc9 8144995: Move sun.misc.HexDumpEncoder to sun.security.util
chegar
parents: 27957
diff changeset
    43
import sun.security.util.HexDumpEncoder;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
import sun.security.krb5.Confounder;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
import sun.security.krb5.internal.crypto.KeyUsage;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
import sun.security.krb5.KrbCryptoException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
 * Implements Derive Key cryptography functionality as defined in RFC 3961.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
 * http://www.ietf.org/rfc/rfc3961.txt
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
 * This is an abstract class. Concrete subclasses need to implement
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
 * the abstract methods.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
public abstract class DkCrypto {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
    protected static final boolean debug = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
    // These values correspond to the ASCII encoding for the string "kerberos"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
    static final byte[] KERBEROS_CONSTANT =
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
        {0x6b, 0x65, 0x72, 0x62, 0x65, 0x72, 0x6f, 0x73};
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
    protected abstract int getKeySeedLength();  // in bits
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
    protected abstract byte[] randomToKey(byte[] in);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
    protected abstract Cipher getCipher(byte[] key, byte[] ivec, int mode)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
        throws GeneralSecurityException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
    public abstract int getChecksumLength();  // in bytes
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
    protected abstract byte[] getHmac(byte[] key, byte[] plaintext)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
        throws GeneralSecurityException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
     * From RFC 3961.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
     * encryption function       conf = random string of length c
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
     *                     pad = shortest string to bring confounder
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
     *                           and plaintext to a length that's a
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
     *                           multiple of m
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
     *                     (C1, newIV) = E(Ke, conf | plaintext | pad,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
     *                                     oldstate.ivec)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
     *                    H1 = HMAC(Ki, conf | plaintext | pad)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
     *                     ciphertext =  C1 | H1[1..h]
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
     *                     newstate.ivec = newIV
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
     * @param ivec initial vector to use when initializing the cipher; if null,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
     *     then blocksize number of zeros are used,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
     * @param new_ivec if non-null, it is updated upon return to be the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
     *       new ivec to use when calling encrypt next time
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
    public byte[] encrypt(byte[] baseKey, int usage,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
        byte[] ivec, byte[] new_ivec, byte[] plaintext, int start, int len)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
        throws GeneralSecurityException, KrbCryptoException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
        if (!KeyUsage.isValid(usage)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
            throw new GeneralSecurityException("Invalid key usage number: "
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
                                                + usage);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
        byte[] Ke = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
        byte[] Ki = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
            // Derive encryption key
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
            byte[] constant = new byte[5];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
            constant[0] = (byte) ((usage>>24)&0xff);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
            constant[1] = (byte) ((usage>>16)&0xff);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
            constant[2] = (byte) ((usage>>8)&0xff);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
            constant[3] = (byte) (usage&0xff);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
            constant[4] = (byte) 0xaa;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
            Ke = dk(baseKey, constant);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
            if (debug) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
                System.err.println("usage: " + usage);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
                if (ivec != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
                    traceOutput("old_state.ivec", ivec, 0, ivec.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
                traceOutput("plaintext", plaintext, start, Math.min(len, 32));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
                traceOutput("constant", constant, 0, constant.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
                traceOutput("baseKey", baseKey, 0, baseKey.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
                traceOutput("Ke", Ke, 0, Ke.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
            // Encrypt
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
            // C1 = E(Ke, conf | plaintext | pad, oldivec)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
            Cipher encCipher = getCipher(Ke, ivec, Cipher.ENCRYPT_MODE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
            int blockSize = encCipher.getBlockSize();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
            byte[] confounder = Confounder.bytes(blockSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
            int plainSize = roundup(confounder.length + len, blockSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
            if (debug) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
                System.err.println("confounder = " + confounder.length +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
                    "; plaintext = " + len + "; padding = " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
                    (plainSize - confounder.length - len) + "; total = " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
                        plainSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
                traceOutput("confounder", confounder, 0, confounder.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
            byte[] toBeEncrypted = new byte[plainSize];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
            System.arraycopy(confounder, 0, toBeEncrypted,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
                                0, confounder.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
            System.arraycopy(plaintext, start, toBeEncrypted,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
                                confounder.length, len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
            // Set padding bytes to zero
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
            Arrays.fill(toBeEncrypted, confounder.length + len, plainSize,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
                        (byte)0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
            int cipherSize = encCipher.getOutputSize(plainSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
            int ccSize =  cipherSize + getChecksumLength();  // cipher | hmac
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
            byte[] ciphertext = new byte[ccSize];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
            encCipher.doFinal(toBeEncrypted, 0, plainSize, ciphertext, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
            // Update ivec for next operation
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
            // (last blockSize bytes of ciphertext)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
            // newstate.ivec = newIV
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
            if (new_ivec != null && new_ivec.length == blockSize) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
                System.arraycopy(ciphertext,  cipherSize - blockSize,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
                    new_ivec, 0, blockSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
                if (debug) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
                    traceOutput("new_ivec", new_ivec, 0, new_ivec.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
            // Derive integrity key
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
            constant[4] = (byte) 0x55;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
            Ki = dk(baseKey, constant);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
            if (debug) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
                traceOutput("constant", constant, 0, constant.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
                traceOutput("Ki", Ki, 0, Ke.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
            // Generate checksum
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
            // H1 = HMAC(Ki, conf | plaintext | pad)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
            byte[] hmac = getHmac(Ki, toBeEncrypted);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
            if (debug) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
                traceOutput("hmac", hmac, 0, hmac.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
                traceOutput("ciphertext", ciphertext, 0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
                                Math.min(ciphertext.length, 32));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
            // C1 | H1[1..h]
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
            System.arraycopy(hmac, 0, ciphertext, cipherSize,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
                                getChecksumLength());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
            return ciphertext;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
        } finally {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
            if (Ke != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
                Arrays.fill(Ke, 0, Ke.length, (byte) 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
            if (Ki != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
                Arrays.fill(Ki, 0, Ki.length, (byte) 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
     * Performs encryption using given key only; does not add
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
     * confounder, padding, or checksum. Incoming data to be encrypted
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
     * assumed to have the correct blocksize.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
     * Ignore key usage.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
    public byte[] encryptRaw(byte[] baseKey, int usage,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
        byte[] ivec, byte[] plaintext, int start, int len)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
        throws GeneralSecurityException, KrbCryptoException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
        if (debug) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
            System.err.println("usage: " + usage);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
            if (ivec != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
                traceOutput("old_state.ivec", ivec, 0, ivec.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
            traceOutput("plaintext", plaintext, start, Math.min(len, 32));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
            traceOutput("baseKey", baseKey, 0, baseKey.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
        // Encrypt
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
        Cipher encCipher = getCipher(baseKey, ivec, Cipher.ENCRYPT_MODE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
        int blockSize = encCipher.getBlockSize();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
        if ((len % blockSize) != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
            throw new GeneralSecurityException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
                "length of data to be encrypted (" + len +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
                ") is not a multiple of the blocksize (" + blockSize + ")");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
        int cipherSize = encCipher.getOutputSize(len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
        byte[] ciphertext = new byte[cipherSize];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
        encCipher.doFinal(plaintext, 0, len, ciphertext, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
        return ciphertext;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
     * Decrypts data using specified key and initial vector.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
     * @param baseKey encryption key to use
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
     * @param ciphertext  encrypted data to be decrypted
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
     * @param usage ignored
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
    public byte[] decryptRaw(byte[] baseKey, int usage, byte[] ivec,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
        byte[] ciphertext, int start, int len)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
        throws GeneralSecurityException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
        if (debug) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
            System.err.println("usage: " + usage);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
            if (ivec != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
                traceOutput("old_state.ivec", ivec, 0, ivec.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
            traceOutput("ciphertext", ciphertext, start, Math.min(len, 32));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
            traceOutput("baseKey", baseKey, 0, baseKey.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
        Cipher decCipher = getCipher(baseKey, ivec, Cipher.DECRYPT_MODE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
        int blockSize = decCipher.getBlockSize();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
        if ((len % blockSize) != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
            throw new GeneralSecurityException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
                "length of data to be decrypted (" + len +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
                ") is not a multiple of the blocksize (" + blockSize + ")");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
        byte[] decrypted = decCipher.doFinal(ciphertext, start, len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
        if (debug) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
            traceOutput("decrypted", decrypted, 0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
                Math.min(decrypted.length, 32));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
        return decrypted;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
     * @param baseKey key from which keys are to be derived using usage
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
     * @param ciphertext  E(Ke, conf | plaintext | padding, ivec) | H1[1..h]
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
    public byte[] decrypt(byte[] baseKey, int usage, byte[] ivec,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
        byte[] ciphertext, int start, int len) throws GeneralSecurityException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
        if (!KeyUsage.isValid(usage)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
            throw new GeneralSecurityException("Invalid key usage number: "
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
                                                + usage);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
        byte[] Ke = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
        byte[] Ki = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
            // Derive encryption key
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
            byte[] constant = new byte[5];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
            constant[0] = (byte) ((usage>>24)&0xff);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
            constant[1] = (byte) ((usage>>16)&0xff);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
            constant[2] = (byte) ((usage>>8)&0xff);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
            constant[3] = (byte) (usage&0xff);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
            constant[4] = (byte) 0xaa;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
            Ke = dk(baseKey, constant);  // Encryption key
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
            if (debug) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
                System.err.println("usage: " + usage);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
                if (ivec != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
                    traceOutput("old_state.ivec", ivec, 0, ivec.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
                traceOutput("ciphertext", ciphertext, start, Math.min(len, 32));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
                traceOutput("constant", constant, 0, constant.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
                traceOutput("baseKey", baseKey, 0, baseKey.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
                traceOutput("Ke", Ke, 0, Ke.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
            Cipher decCipher = getCipher(Ke, ivec, Cipher.DECRYPT_MODE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
            int blockSize = decCipher.getBlockSize();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
            // Decrypt [confounder | plaintext | padding] (without checksum)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
            int cksumSize = getChecksumLength();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
            int cipherSize = len - cksumSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
            byte[] decrypted = decCipher.doFinal(ciphertext, start, cipherSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
            if (debug) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
                traceOutput("decrypted", decrypted, 0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
                                Math.min(decrypted.length, 32));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
            // decrypted = [confounder | plaintext | padding]
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
            // Derive integrity key
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
            constant[4] = (byte) 0x55;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
            Ki = dk(baseKey, constant);  // Integrity key
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
            if (debug) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
                traceOutput("constant", constant, 0, constant.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
                traceOutput("Ki", Ki, 0, Ke.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
            // Verify checksum
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
            // H1 = HMAC(Ki, conf | plaintext | pad)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
            byte[] calculatedHmac = getHmac(Ki, decrypted);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
            if (debug) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
                traceOutput("calculated Hmac", calculatedHmac, 0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
                    calculatedHmac.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
                traceOutput("message Hmac", ciphertext, cipherSize,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
                    cksumSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
            boolean cksumFailed = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
            if (calculatedHmac.length >= cksumSize) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
                for (int i = 0; i < cksumSize; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
                    if (calculatedHmac[i] != ciphertext[cipherSize+i]) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
                        cksumFailed = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
                        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
            if (cksumFailed) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
                throw new GeneralSecurityException("Checksum failed");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
            // Prepare decrypted msg and ivec to be returned
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
            // Last blockSize bytes of ciphertext without checksum
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
            if (ivec != null && ivec.length == blockSize) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
                System.arraycopy(ciphertext,  start + cipherSize - blockSize,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
                    ivec, 0, blockSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
                if (debug) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
                    traceOutput("new_state.ivec", ivec, 0, ivec.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
            // Get rid of confounder
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
            // [plaintext | padding]
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
            byte[] plaintext = new byte[decrypted.length - blockSize];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
            System.arraycopy(decrypted, blockSize, plaintext,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
                                0, plaintext.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
            return plaintext; // padding still there
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
        } finally {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
            if (Ke != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
                Arrays.fill(Ke, 0, Ke.length, (byte) 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
            if (Ki != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
                Arrays.fill(Ki, 0, Ki.length, (byte) 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
    // Round up to the next blocksize
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
    int roundup(int n, int blocksize) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
        return (((n + blocksize - 1) / blocksize) * blocksize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
    public byte[] calculateChecksum(byte[] baseKey, int usage, byte[] input,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
        int start, int len) throws GeneralSecurityException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
        if (!KeyUsage.isValid(usage)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
            throw new GeneralSecurityException("Invalid key usage number: "
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
                                                + usage);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
        // Derive keys
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
        byte[] constant = new byte[5];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
        constant[0] = (byte) ((usage>>24)&0xff);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
        constant[1] = (byte) ((usage>>16)&0xff);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
        constant[2] = (byte) ((usage>>8)&0xff);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
        constant[3] = (byte) (usage&0xff);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
        constant[4] = (byte) 0x99;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
        byte[] Kc = dk(baseKey, constant);  // Checksum key
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
        if (debug) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
            System.err.println("usage: " + usage);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
            traceOutput("input", input, start, Math.min(len, 32));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
            traceOutput("constant", constant, 0, constant.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
            traceOutput("baseKey", baseKey, 0, baseKey.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
            traceOutput("Kc", Kc, 0, Kc.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
            // Generate checksum
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
            // H1 = HMAC(Kc, input)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
            byte[] hmac = getHmac(Kc, input);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
            if (debug) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
                traceOutput("hmac", hmac, 0, hmac.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
            if (hmac.length == getChecksumLength()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
                return hmac;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
            } else if (hmac.length > getChecksumLength()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
                byte[] buf = new byte[getChecksumLength()];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
                System.arraycopy(hmac, 0, buf, 0, buf.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
                return buf;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
                throw new GeneralSecurityException("checksum size too short: " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
                    hmac.length + "; expecting : " + getChecksumLength());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
        } finally {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
            Arrays.fill(Kc, 0, Kc.length, (byte)0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
    // DK(Key, Constant) = random-to-key(DR(Key, Constant))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
    byte[] dk(byte[] key, byte[] constant)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
        throws GeneralSecurityException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
        return randomToKey(dr(key, constant));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
     * From RFC 3961.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
     * DR(Key, Constant) = k-truncate(E(Key, Constant,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
     *                                  initial-cipher-state))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
     * Here DR is the random-octet generation function described below, and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
     * DK is the key-derivation function produced from it.  In this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
     * construction, E(Key, Plaintext, CipherState) is a cipher, Constant is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
     * a well-known constant determined by the specific usage of this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
     * function, and k-truncate truncates its argument by taking the first k
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
     * bits.  Here, k is the key generation seed length needed for the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
     * encryption system.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
     * The output of the DR function is a string of bits; the actual key is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
     * produced by applying the cryptosystem's random-to-key operation on
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
     * this bitstring.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
     * If the Constant is smaller than the cipher block size of E, then it
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
     * must be expanded with n-fold() so it can be encrypted.  If the output
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
     * of E is shorter than k bits it is fed back into the encryption as
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
     * many times as necessary.  The construct is as follows (where |
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
     * indicates concatentation):
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
     * K1 = E(Key, n-fold(Constant), initial-cipher-state)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
     * K2 = E(Key, K1, initial-cipher-state)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
     * K3 = E(Key, K2, initial-cipher-state)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
     * K4 = ...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
     * DR(Key, Constant) = k-truncate(K1 | K2 | K3 | K4 ...)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
    private byte[] dr(byte[] key, byte[] constant)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
        throws GeneralSecurityException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
        Cipher encCipher = getCipher(key, null, Cipher.ENCRYPT_MODE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
        int blocksize = encCipher.getBlockSize();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
        if (constant.length != blocksize) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
            constant = nfold(constant, blocksize * 8);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
        byte[] toBeEncrypted = constant;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
        int keybytes = (getKeySeedLength()>>3);  // from bits to bytes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
        byte[] rawkey = new byte[keybytes];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
        int posn = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
        /* loop encrypting the blocks until enough key bytes are generated */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
        int n = 0, len;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
        while (n < keybytes) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
            if (debug) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
                System.err.println("Encrypting: " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
                    bytesToString(toBeEncrypted));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
            byte[] cipherBlock = encCipher.doFinal(toBeEncrypted);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
            if (debug) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
                System.err.println("K: " + ++posn + " = " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
                    bytesToString(cipherBlock));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
            len = (keybytes - n <= cipherBlock.length ? (keybytes - n) :
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
                cipherBlock.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
            if (debug) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
                System.err.println("copying " + len + " key bytes");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
            System.arraycopy(cipherBlock, 0, rawkey, n, len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
            n += len;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
            toBeEncrypted = cipherBlock;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
        return rawkey;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
// ---------------------------------
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
    // From MIT-1.3.1 distribution
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
     * n-fold(k-bits):
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
     *   l = lcm(n,k)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
     *   r = l/k
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
     * s = k-bits | k-bits rot 13 | k-bits rot 13*2 | ... | k-bits rot 13*(r-1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
     * compute the 1's complement sum:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
     * n-fold = s[0..n-1]+s[n..2n-1]+s[2n..3n-1]+..+s[(k-1)*n..k*n-1]
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
     * representation: msb first, assume n and k are multiples of 8, and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
     *  that k>=16.  this is the case of all the cryptosystems which are
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
     *  likely to be used.  this function can be replaced if that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
     *  assumption ever fails.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
    /* input length is in bits */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
    static byte[] nfold(byte[] in, int outbits) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
        int inbits = in.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
        outbits >>= 3;    // count in bytes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
        /* first compute lcm(n,k) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
        int a, b, c, lcm;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
        a = outbits;  // n
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
        b = inbits;   // k
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
        while (b != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
            c = b;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
            b = a % b;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
            a = c;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
        lcm = outbits*inbits/a;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
        if (debug) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
            System.err.println("k: " + inbits);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
            System.err.println("n: " + outbits);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
            System.err.println("lcm: " + lcm);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
        /* now do the real work */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
        byte[] out = new byte[outbits];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
        Arrays.fill(out, (byte)0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
        int thisbyte = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
        int msbit, i, bval, oval;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
        // this will end up cycling through k lcm(k,n)/k times, which
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
        // is correct
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
        for (i = lcm-1; i >= 0; i--) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
            /* compute the msbit in k which gets added into this byte */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
            msbit = (/* first, start with msbit in the first, unrotated byte */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
                ((inbits<<3)-1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
                /* then, for each byte, shift to right for each repetition */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
                + (((inbits<<3)+13)*(i/inbits))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
                /* last, pick out correct byte within that shifted repetition */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
                + ((inbits-(i%inbits)) << 3)) % (inbits << 3);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
            /* pull out the byte value itself */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
            // Mask off values using &0xff to get only the lower byte
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
            // Use >>> to avoid sign extension
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
            bval =  ((((in[((inbits-1)-(msbit>>>3))%inbits]&0xff)<<8)|
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
                (in[((inbits)-(msbit>>>3))%inbits]&0xff))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
                >>>((msbit&7)+1))&0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
            System.err.println("((" +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
                ((in[((inbits-1)-(msbit>>>3))%inbits]&0xff)<<8)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
                + "|" + (in[((inbits)-(msbit>>>3))%inbits]&0xff) + ")"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
                + ">>>" + ((msbit&7)+1) + ")&0xff = " + bval);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
            */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
            thisbyte += bval;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
            /* do the addition */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
            // Mask off values using &0xff to get only the lower byte
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
            oval = (out[i%outbits]&0xff);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
            thisbyte += oval;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
            out[i%outbits] = (byte) (thisbyte&0xff);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
            if (debug) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
                System.err.println("msbit[" + i + "] = " +  msbit + "\tbval=" +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
                    Integer.toHexString(bval) + "\toval=" +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
                    Integer.toHexString(oval)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
                    + "\tsum = " + Integer.toHexString(thisbyte));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
            /* keep around the carry bit, if any */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
            thisbyte >>>= 8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
            if (debug) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
                System.err.println("carry=" + thisbyte);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
        /* if there's a carry bit left over, add it back in */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
        if (thisbyte != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
            for (i = outbits-1; i >= 0; i--) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
                /* do the addition */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
                thisbyte += (out[i]&0xff);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
                out[i] = (byte) (thisbyte&0xff);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
                /* keep around the carry bit, if any */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
                thisbyte >>>= 8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
        return out;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
    // Routines used for debugging
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
    static String bytesToString(byte[] digest) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
        // Get character representation of digest
24969
afa6934dd8e8 8041679: Replace uses of StringBuffer with StringBuilder within core library classes
psandoz
parents: 5506
diff changeset
   639
        StringBuilder digestString = new StringBuilder();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
        for (int i = 0; i < digest.length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
            if ((digest[i] & 0x000000ff) < 0x10) {
27957
24b4e6082f19 8055723: Replace concat String to append in StringBuilder parameters (dev)
weijun
parents: 25859
diff changeset
   643
                digestString.append('0').append(Integer.toHexString(digest[i] & 0x000000ff));
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
                digestString.append(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
                    Integer.toHexString(digest[i] & 0x000000ff));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
        return digestString.toString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
    private static byte[] binaryStringToBytes(String str) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
        char[] usageStr = str.toCharArray();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
        byte[] usage = new byte[usageStr.length/2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
        for (int i = 0; i < usage.length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
            byte a = Byte.parseByte(new String(usageStr, i*2, 1), 16);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
            byte b = Byte.parseByte(new String(usageStr, i*2 + 1, 1), 16);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
            usage[i] = (byte) ((a<<4)|b);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
        return usage;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
    static void traceOutput(String traceTag, byte[] output, int offset,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
        int len) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
            ByteArrayOutputStream out = new ByteArrayOutputStream(len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
            new HexDumpEncoder().encodeBuffer(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
                new ByteArrayInputStream(output, offset, len), out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
            System.err.println(traceTag + ":" + out.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
        } catch (Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
// String.getBytes("UTF-8");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
// Do this instead of using String to avoid making password immutable
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
    static byte[] charToUtf8(char[] chars) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
        Charset utf8 = Charset.forName("UTF-8");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
        CharBuffer cb = CharBuffer.wrap(chars);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
        ByteBuffer bb = utf8.encode(cb);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
        int len = bb.limit();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
        byte[] answer = new byte[len];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
        bb.get(answer, 0, len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
        return answer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
    static byte[] charToUtf16(char[] chars) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
        Charset utf8 = Charset.forName("UTF-16LE");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
        CharBuffer cb = CharBuffer.wrap(chars);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
        ByteBuffer bb = utf8.encode(cb);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
        int len = bb.limit();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
        byte[] answer = new byte[len];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
        bb.get(answer, 0, len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
        return answer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
}