001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.harmony.auth.internal.kerberos.v5;
019:
020: import java.io.IOException;
021:
022: import javax.crypto.Cipher;
023: import javax.crypto.SecretKey;
024: import javax.crypto.spec.IvParameterSpec;
025:
026: import org.apache.harmony.security.asn1.ASN1Explicit;
027: import org.apache.harmony.security.asn1.ASN1Integer;
028: import org.apache.harmony.security.asn1.ASN1OctetString;
029: import org.apache.harmony.security.asn1.ASN1Sequence;
030: import org.apache.harmony.security.asn1.ASN1Type;
031: import org.apache.harmony.security.asn1.BerInputStream;
032:
033: /**
034: * @see http://www.ietf.org/rfc/rfc4120.txt
035: */
036: public class EncryptedData {
037:
038: /**
039: * DES in CBC mode with CRC-based checksum
040: */
041: public static final int DES_CBC_CRC = 1;
042:
043: /**
044: * DES in CBC mode with CRC-based checksum
045: */
046: public static final int DES_CBC_MD4 = 2;
047:
048: /**
049: * DES in CBC mode with CRC-based checksum
050: */
051: public static final int DES_CBC_MD5 = 3;
052:
053: private final int etype;
054:
055: private final int kvno;
056:
057: private final byte[] cipher;
058:
059: public EncryptedData(int etype, int kvno, byte[] cipher) {
060: this .etype = etype;
061: this .kvno = kvno;
062: this .cipher = cipher;
063: }
064:
065: public int getEtype() {
066: return etype;
067: }
068:
069: public int getKvno() {
070: return kvno;
071: }
072:
073: public byte[] getCipher() {
074: return cipher;
075: }
076:
077: public byte[] decrypt(SecretKey key) {
078:
079: int offset;
080:
081: IvParameterSpec initCipherState;
082: switch (etype) {
083: case DES_CBC_CRC:
084: offset = 12;// confounder(8)+CRC-32 checksum(4)
085: // copy of original key
086: initCipherState = new IvParameterSpec(key.getEncoded());
087: break;
088: case DES_CBC_MD4:
089: case DES_CBC_MD5:
090: offset = 24;// confounder(8)+ MD4/5 checksum(16)
091: // all-zero
092: initCipherState = new IvParameterSpec(new byte[] { 0, 0, 0,
093: 0, 0, 0, 0, 0, });
094: break;
095: default:
096: throw new RuntimeException();//FIXME not implemented yet
097: }
098:
099: try {
100: Cipher dcipher = Cipher.getInstance("DES/CBC/NoPadding");
101:
102: dcipher.init(Cipher.DECRYPT_MODE, key, initCipherState);
103:
104: byte[] tmp = dcipher.doFinal(cipher);
105:
106: // TODO: verify checksum
107:
108: // cat out: confounder and checksum bytes
109: // TODO: how to do the same for padding bytes?
110: byte[] result = new byte[tmp.length - offset];
111: System.arraycopy(tmp, offset, result, 0, result.length);
112:
113: return result;
114: } catch (Exception e) {
115: throw new RuntimeException(e);
116: }
117: }
118:
119: /**
120: * <pre>
121: * EncryptedData ::= SEQUENCE {
122: * etype [0] Int32 -- EncryptionType --,
123: * kvno [1] UInt32 OPTIONAL,
124: * cipher [2] OCTET STRING -- ciphertext
125: * }
126: * </pre>
127: */
128: static final ASN1Sequence ASN1 = new ASN1Sequence(new ASN1Type[] {
129: // TODO should we define Int32 type?
130: new ASN1Explicit(0, ASN1Integer.getInstance()), // etype
131: // TODO should we define UInt32 type?
132: new ASN1Explicit(1, ASN1Integer.getInstance()), // kvno
133: // cipher
134: new ASN1Explicit(2, ASN1OctetString.getInstance()), }) {
135: {
136: setOptional(1); // kvno
137: }
138:
139: @Override
140: protected Object getDecodedObject(BerInputStream in)
141: throws IOException {
142: Object[] values = (Object[]) in.content;
143: return new EncryptedData(ASN1Integer.toIntValue(values[0]),
144: ASN1Integer.toIntValue(values[1]),
145: (byte[]) values[2]);
146: }
147:
148: @Override
149: protected void getValues(Object object, Object[] values) {
150: throw new RuntimeException(); //FIXME message
151: }
152: };
153: }
|