制作一个基于EEPROM的"USB"密钥
最近一直在学习单片机C语言,自从看了电影“超能查派”后,就一直想仿制一个里面的那个USB密钥,所以最近研究了下,做出了这么一个东西,经过本作品学到了不少东西


所用单片机:AT89C51
做本作品的用意是来学习I2C通讯,所以程序方面,在网上找了许多类似功能的程序,然后尝试删减修改其功能,比较不同来学习,最终终于实现了想要的功能,也算对I2C有了初步的了解,在此要感谢群友acmilan和张静茹的指导


采用24C08储存密码,然后采用单片机进行读取,对比密码是否符合,考虑到美观问题,所以将此IC封装在了USB插头里,所以得先拆一个USB插头,去除内芯
249207




由于手头没有卡尺等精密测量工具,所以用的普通塑料尺进行测量大小及间距
249208


249209


采用热转印法制作一块PCB
249210



249211


转印效果还是不错的:
249212


腐蚀(使用的TB上买的蓝色环保腐蚀剂,有人说是过硫酸钠,我也不确定):
249213



249214



249215




裁剪成型
249216



将所需原件焊上(为避免USB触点氧化,所以需要镀锡,然后进行打磨):
249217



装进USB头里,正好:
249218



249219



用热熔胶填补内部空间:
249220


找个塑料盖套上,美观些:
249221



249222


哥俩好在内部粘接
249223




成品:
249224




实验后反思:本密钥虽然起到了鉴权的功能,但是存在被复制的风险,所以打算在程序里加一个密码计算公式,每次解锁成功后计算一个新密码写入到密钥里的EEPROM里供下次解锁使用,这样复制者即使复制了密码也没有太大用处了,况且复制者不可能每次都得逞,有大数据来计算公式,所以打算按照这个想法继续改进下。

将PCB上的正负极调换一下可以做到如果插到普通USB口上就自动销毁的目的


效果视频:







点击此处查看视频


源程序:

#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define bool int
#define false 0
#define true 1
       
sbit scl=P2^6;
sbit sda=P2^7;
sbit OUT=P1^1;
       
       
       
void delayus()  
{  
                       
}  
       
void delayXms(uchar x)         
{
 uchar i;
 while(x--)
 {
  for(i=250;i>0;i--)
  {
   _nop_();
   _nop_();
   _nop_();
   _nop_();
  }
 } 
}
       
void iic_start() 
{  
    sda=1;  
    scl=1;  
    delayus();      
    _nop_();           
    sda=0;         
    delayus();     
}  
         
void iic_stop()   
{  
    sda=0;_nop_();    
    scl=1;  
    delayus();      
    sda=1;          
    delayus();     
                                 
}  
         
void iic_sendByte(uchar byteData) 
{  
    uchar i;  
    uchar temp=byteData;  
    for(i=0;i<8;i++)  
    {  
        temp=temp<<1;  
        scl=0;          
        _nop_();         
        sda=CY;        
        _nop_();  
        scl=1;          
        _nop_();          
    }  
         
    scl=0;             
    _nop_();                  
    sda=1;            
    _nop_();  
}  
         
uchar iic_readByte() 
{  
    uchar i,temp;  
    scl=0;              
    _nop_();  
    sda=1;              
    _nop_();  
         
    for(i=0;i<8;i++)  
    {  
        scl=1;           
        delayus();      
                                  
        temp=(temp<<1)|sda;
        scl=0;  
        delayus();        
    }  
    return temp;  
}  
           
   bool IIC_CheckACK() 
{  
    uchar errCounts=255; 
    scl=1;  
    _nop_();  
       
    while(sda)  
    {   
        if(0==errCounts)  
        {  
            scl=0;          
            _nop_();  
            return false;
        }  
        errCounts--;  
    }  
         
    scl=0;             
    _nop_();  
    return true;       
}  
         
void iic_init()   
{  
    scl=1;  
    sda=1;  
    delayus();  
}  
         
void iic_sendACK(bool b_ACK)    
{  
    scl=0;          
    _nop_();  
         
    if(b_ACK)        
    {  
        sda=0;  
    }  
    else         
    {  
        sda=1;  
    }  
         
    _nop_();  
    scl=1;  
    delayus();     
    scl=0;             
    _nop_();  
}  
         
         
void AT24C02_writeByte(uchar address,uchar dataByte)
{  
    iic_start();  
    iic_sendByte(0xa0);
    iic_checkACK();     
    iic_sendByte(address);   
    iic_checkACK();  
    iic_sendByte(dataByte);
    iic_checkACK();  
    iic_stop();  
    delayXms(2);   
             
} 
         
void AT24C02_writeData(uchar address,uchar numBytes,uchar* buf)//写入任意长度数据  
{  
    while(numBytes--)  
    {  
        AT24C02_writeByte(address++,*buf++);  
    }  
}  
         
void AT24C02_readData(uchar beginAddr,uchar dataSize,uchar* buf)//读取任意长度字节  
{  
    iic_start();                   
    iic_sendByte(0xa0);        
    iic_checkACK();            
    iic_sendByte(beginAddr);   
    iic_checkACK();                 
    iic_start();               
    iic_sendByte(0xa1);       
    iic_checkACK();           
    while(dataSize--)             
    {  
        *buf++=iic_readByte();  
        iic_sendACK(dataSize);  
    }  
    iic_stop();                     
}  
      
       
void main()
{
  unsigned char temp1[3]={18,17,16};
  unsigned char temp2[3]={0};
         
  iic_init();
  AT24C02_writeData(0x00,sizeof(temp1),temp1);
  delayXms(5);
  AT24C02_readData(0x00,sizeof(temp2),temp2); 
  delayXms(5);
        
  while(1)
  {
      if(temp2[0]==18|temp2[1]==17|temp2[2]==16)
     {
      OUT=0;
     }
           
  }
       
}

[修改于 4 年前 - 2015-08-08 09:47:55]

来自 快乐DIY
 
2015-8-7 13:20:04
1楼
腐蚀的效果比雕刻还容易控制
折叠评论
加载评论中,请稍候...
折叠评论
2楼
[s::funk:]摸语.......原来USB口里面是24C啊....热转印的不错....看PCB我还以为逗语放了个8Pin的Attiny进去 ...还在想怎么昨天还在群里问24C今天就玩起USB了....
折叠评论
加载评论中,请稍候...
折叠评论
3楼
如果写入密码计算公式,我复制成功了,在你使用之前我使用了一次,那么,复制品就成了合法的了。
你那个原装的就废了。
折叠评论
加载评论中,请稍候...
折叠评论
无语·回忆(作者)
4楼
引用 samsun185:
如果写入密码计算公式,我复制成功了,在你使用之前我使用了一次,那么,复制品就成了合法的了。
你那个原装的就废了。
嗯,确实存在这个问题,如果加一个指纹解锁搭配使用,应该就可以了
折叠评论
加载评论中,请稍候...
折叠评论
5楼
引用 无语·回忆:
嗯,确实存在这个问题,如果加一个指纹解锁搭配使用,应该就可以了
[s::D]所以说你还是放个ATtiny进去根据某种算法计算动态密钥比较好
折叠评论
加载评论中,请稍候...
折叠评论
6楼
引用 张静茹:
腐蚀的效果比雕刻还容易控制
哪个芯片制造还用雕刻
折叠评论
加载评论中,请稍候...
折叠评论
7楼
这样也行?好吧,膜拜
折叠评论
加载评论中,请稍候...
折叠评论
8楼
唔~~~无语做的不错
折叠评论
加载评论中,请稍候...
折叠评论
9楼
那个,可以加一个识别电路,正常正负极就是U盘,对调正负极就是密钥。
折叠评论
加载评论中,请稍候...
折叠评论
10楼
做的还不错啊。。。。。我还以为那是个真的U盘。。。。。
折叠评论
加载评论中,请稍候...
折叠评论
2015-8-8 09:08:10
11楼
建议楼主参考一下NIST的FIPS-140
折叠评论
加载评论中,请稍候...
折叠评论
12楼
我说怎么可以通过USB信号操作EEPROM。
折叠评论
加载评论中,请稍候...
折叠评论
13楼
i2c还可以改进,可以一次写入多个数据,但是要注意 换页。这个可以看芯片的数据手册。

算法你可以参考 双因素认证 。
折叠评论
加载评论中,请稍候...
折叠评论
2015-8-9 06:14:48
14楼
过硫酸钠+硫酸铜
折叠评论
加载评论中,请稍候...
折叠评论
15楼
引用 好大一菇凉:
过硫酸钠+硫酸铜
也可能是过硫酸铵
折叠评论
加载评论中,请稍候...
折叠评论
16楼
青猫摸语。
还以为你要做电脑版的,正纳闷电脑软件是什么呢。
如果只是作为单片机系统的钥匙,USB口并不是最佳选择,RFID才是王道。但是RFID太常见,B格又降低不少。
可以考虑拆个内存条插槽来用,钥匙也做成内存条的形状。金手指多得匪夷所思,完全可以用上单片机的所有I/O口来做并行通讯,协议自定。
一种设想:使用单片机所有模拟输入口,每个口接收特定频率的PWM信号,这些由钥匙发出的信号会模拟一段音乐,例如:
2212445
221211
2212456
656542
2212445
...
每个数字代表一个模拟通道,并对应某个特定频率,如“1”就是“哆”
钥匙储存1分钟的音乐,每次随机播放3秒,单片机锁根据音符的前后顺序来判断是否真钥匙。
这样的神经病密码,只有哈士奇能破解。
折叠评论
3
加载评论中,请稍候...
折叠评论
17楼
,,硬件加密芯片如何,,只听说过,没见过
折叠评论
加载评论中,请稍候...
折叠评论
2015-8-10 08:25:10
18楼
最近也在搞单片机系统加密的东西!
这个思路很不错哦。但是如果密钥和系统都给客户的话。
有没有什么好的方法来加密呢?

现在芯片破解商家的技术能做到模拟外界接口的通信流。
用加密芯片是个不错的选择。
但是如果能利用单片机自身的唯一ID号生成动态密码,有什么好的算法可以借鉴嘛?

可以让复制二进制码的山寨厂家,烧录进单片机。通过对比ID号实现IAP自擦除FLASH内容。
折叠评论
加载评论中,请稍候...
折叠评论
2015-8-23 23:38:35
2015-8-23 23:38:35
19楼
有给很吊的想法 用18B20来做加密,装在一个耳机插头里,正好3个脚,18b20里面有ID呢而且是唯一的
折叠评论
加载评论中,请稍候...
折叠评论
2019-7-31 14:14:00
2019-7-31 14:14:00
20楼
引用 laji3865689 发表于 16 楼的内容:
青猫摸语。还以为你要做电脑版的,正纳闷电脑软件是什么呢。如果只是作为单片机系统的钥匙,USB口并不是.....

有意思

折叠评论
加载评论中,请稍候...
折叠评论
21楼
引用 金坷居士 发表于 19 楼的内容:
有给很吊的想法 用18B20来做加密,装在一个耳机插头里,正好3个脚,18b20里面有ID呢而且是唯.....

有一种东西叫做硅序列号

可以百度一下,就是一个小芯片,3个引脚,里边有一个唯一的48位二进制序列号,不可修改

折叠评论
加载评论中,请稍候...
折叠评论
2019-8-1 20:59:57
2019-8-1 20:59:57
22楼

不如参考那些专门做加密狗的公司的方案,国内的深思、飞天,国外的Wibu,Gemalto等等。最好可以将需要保护的程序的部分关键计算代码内置在硬件中,或者至少部分关键数据在加密狗内解密。比如用Gemalto/Sentinel HASP的 hasp_decrypt解密每一组关键数据,有一款软件将它保存文件的格式定义加密,如果没有加密狗,就算其他验证都被绕过,也无法正确读取保存文件。软件本身也要最好要加外壳保护。用的单片机最好是安全型的,否则有能力的人导出固件,往IDA里一拖,你就就完蛋了。

折叠评论
加载评论中,请稍候...
折叠评论
2019-8-2 03:12:56
23楼

真的很逗的东西很好玩 鼓励一下


折叠评论
加载评论中,请稍候...
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

插入资源
全部
图片
视频
音频
附件
全部
未使用
已使用
正在上传
空空如也~
上传中..{{f.progress}}%
处理中..
上传失败,点击重试
{{f.name}}
空空如也~
(视频){{r.oname}}
{{selectedResourcesId.indexOf(r.rid) + 1}}
ID:{{user.uid}}
{{user.username}}
{{user.info.certsName}}
{{user.description}}
{{format("YYYY/MM/DD", user.toc)}}注册,{{fromNow(user.tlv)}}活动
{{submitted?"":"投诉"}}
请选择违规类型:
{{reason.description}}
支持的图片格式:jpg, jpeg, png