view src/com/five_ten_sg/connectbot/util/EntropyView.java @ 57:e0c68988fe2e
tn5250
start tn5250 integration
author |
Carl Byington <carl@five-ten-sg.com> |
date |
Wed, 11 Jun 2014 14:30:19 -0700 (2014-06-11) |
parents |
0ce5cc452d02 |
children |
|
line source
/*
* ConnectBot: simple, powerful, open-source SSH client for Android
* Copyright 2007 Kenny Root, Jeffrey Sharkey
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.five_ten_sg.connectbot.util;
import java.util.Vector;
import com.five_ten_sg.connectbot.R;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class EntropyView extends View {
private static final int SHA1_MAX_BYTES = 20;
private static final int MILLIS_BETWEEN_INPUTS = 50;
private Paint mPaint;
private FontMetrics mFontMetrics;
private boolean mFlipFlop;
private long mLastTime;
private Vector<OnEntropyGatheredListener> listeners;
private byte[] mEntropy;
private int mEntropyByteIndex;
private int mEntropyBitIndex;
private int splitText = 0;
private float lastX = 0.0f, lastY = 0.0f;
public EntropyView(Context context) {
super(context);
setUpEntropy();
}
public EntropyView(Context context, AttributeSet attrs) {
super(context, attrs);
setUpEntropy();
}
private void setUpEntropy() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setTypeface(Typeface.DEFAULT);
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setTextSize(16);
mPaint.setColor(Color.WHITE);
mFontMetrics = mPaint.getFontMetrics();
mEntropy = new byte[SHA1_MAX_BYTES];
mEntropyByteIndex = 0;
mEntropyBitIndex = 0;
listeners = new Vector<OnEntropyGatheredListener>();
}
public void addOnEntropyGatheredListener(OnEntropyGatheredListener listener) {
listeners.add(listener);
}
public void removeOnEntropyGatheredListener(OnEntropyGatheredListener listener) {
listeners.remove(listener);
}
@Override
public void onDraw(Canvas c) {
String prompt = String.format(getResources().getString(R.string.pubkey_touch_prompt),
(int)(100.0 * (mEntropyByteIndex / 20.0)) + (int)(5.0 * (mEntropyBitIndex / 8.0)));
if (splitText > 0 ||
mPaint.measureText(prompt) > (getWidth() * 0.8)) {
if (splitText == 0)
splitText = prompt.indexOf(" ", prompt.length() / 2);
c.drawText(prompt.substring(0, splitText),
getWidth() / 2.0f,
getHeight() / 2.0f + (mPaint.ascent() + mPaint.descent()),
mPaint);
c.drawText(prompt.substring(splitText),
getWidth() / 2.0f,
getHeight() / 2.0f - (mPaint.ascent() + mPaint.descent()),
mPaint);
}
else {
c.drawText(prompt,
getWidth() / 2.0f,
getHeight() / 2.0f - (mFontMetrics.ascent + mFontMetrics.descent) / 2,
mPaint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mEntropyByteIndex >= SHA1_MAX_BYTES
|| lastX == event.getX()
|| lastY == event.getY())
return true;
// Only get entropy every 200 milliseconds to ensure the user has moved around.
long now = System.currentTimeMillis();
if ((now - mLastTime) < MILLIS_BETWEEN_INPUTS)
return true;
else
mLastTime = now;
byte input;
lastX = event.getX();
lastY = event.getY();
// Get the lowest 4 bits of each X, Y input and concat to the entropy-gathering
// string.
if (mFlipFlop)
input = (byte)((((int)lastX & 0x0F) << 4) | ((int)lastY & 0x0F));
else
input = (byte)((((int)lastY & 0x0F) << 4) | ((int)lastX & 0x0F));
mFlipFlop = !mFlipFlop;
for (int i = 0; i < 4 && mEntropyByteIndex < SHA1_MAX_BYTES; i++) {
if ((input & 0x3) == 0x1) {
mEntropy[mEntropyByteIndex] <<= 1;
mEntropy[mEntropyByteIndex] |= 1;
mEntropyBitIndex++;
input >>= 2;
}
else if ((input & 0x3) == 0x2) {
mEntropy[mEntropyByteIndex] <<= 1;
mEntropyBitIndex++;
input >>= 2;
}
if (mEntropyBitIndex >= 8) {
mEntropyBitIndex = 0;
mEntropyByteIndex++;
}
}
// SHA1PRNG only keeps 160 bits of entropy.
if (mEntropyByteIndex >= SHA1_MAX_BYTES) {
for (OnEntropyGatheredListener listener : listeners) {
listener.onEntropyGathered(mEntropy);
}
}
invalidate();
return true;
}
}