【求助】关于ECC的C语言实现,除法精度不够,结果偏差问题?

沈万三gz 2013-07-31 09:16:31
hello,我用C 语言编写Ecc的加解密算法,计算倍乘KG用的方法是:
x1=x2,计算p=(3x^2+a)/2y1; x3=p^2-2p; y3=p(x1-x3)-y1;
x1!=x2,计算p=(y2-y1)/(x1-x2);x3=p^2-x1-x2; y3=p(x1-x3)-y1;

由于这里用了除法,但是C语言中除法除不尽的时候,自动截去结尾,导致结果计算出现错误,计算的KG(x,y)根本就不在曲线上,这个怎么办?

http://bbs.pediy.com/showthread.php?t=176366&highlight=
...全文
473 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
max_min_ 2013-07-31
  • 打赏
  • 举报
回复

说错了
即使
double类型 也是很不精确的,也是会有数据丢失的!
这个貌似要当作大数据来处理,
分割开,整数部分处理,小数部分另外处理!然后再结合一起!
max_min_ 2013-07-31
  • 打赏
  • 举报
回复

即使
double类型 也是精确的,也是会有数据丢失的!
这个貌似要当作大数据来处理,
分割开,整数部分处理,小数部分另外处理!然后再结合一起!
沈万三gz 2013-07-31
  • 打赏
  • 举报
回复
问题不是除法精度不够,问题是ECC算法的倍乘怎么实现的问题。 我用的是上面的方法,直接用算术计算,但是很明显C语言实现不了这种功能。 但是我看别人也是用c语言,写出来了ecc算法,他们的代码还没有看懂,所以想问下有没有人写过这种,具体是怎么实现的
zhctj159 2013-07-31
  • 打赏
  • 举报
回复
难不成还要改进除法指令??问题大概不在于此
沈万三gz 2013-07-31
  • 打赏
  • 举报
回复
double 也是一样的吧,只是多了几位小数而已,只要有四舍五入,结果就和纸面计算的不一样,那么后面计算的时候,就得不到预想的结果了。
tsakang 2013-07-31
  • 打赏
  • 举报
回复
把所有的变量都定义成 double 类型的试试
沈万三gz 2013-07-31
  • 打赏
  • 举报
回复
刚刚回去看资料,k=(y1-y2)/(x1-x2);这里不是除法,是乘以逆元,多谢各位帮助。
沈万三gz 2013-07-31
  • 打赏
  • 举报
回复
楼上的这段代码很强大,学习了! 我想知道的是ECC(椭圆曲线)加密的C语言实现,具体的倍乘是怎么设计的,网上的代码有很多是改编杭电的一个代码,那段代码我也调试过,加解密显示是正确的,但是进去在倍乘函数中用私钥(r)计算倍乘的时候,结果不等于公钥(P)计算的结果,即k*P=r*k*G; 我理解这里的问题: 主要是前面计算P+Q=R的时候,用了除法,而除法是有舍入的,导致后面的结果就不是加法计算的结果。 现在就不知道该怎么办了?
赵4老师 2013-07-31
  • 打赏
  • 举报
回复
// 按下列数级计算e的近视值,使e有小数点后1000位有效数字。
// e=1+1/1!+1/2!+1/3!+......1/n!
#include <iostream>
#include <string>
using namespace std;
inline int compare(string str1,string str2) {//相等返回0,大于返回1,小于返回-1
         if (str1.size()>str2.size()) return 1; //长度长的整数大于长度小的整数
    else if (str1.size()<str2.size()) return -1;
    else                              return str1.compare(str2); //若长度相等,则头到尾按位比较
}
string SUB_INT(string str1,string str2);
string ADD_INT(string str1,string str2) {//高精度加法
    int sign=1; //sign 为符号位
    string str;
    if (str1[0]=='-') {
        if (str2[0]=='-') {
            sign=-1;
            str=ADD_INT(str1.erase(0,1),str2.erase(0,1));
        } else {
            str=SUB_INT(str2,str1.erase(0,1));
        }
    } else {
        if (str2[0]=='-') {
            str=SUB_INT(str1,str2.erase(0,1));
        } else { //把两个整数对齐,短整数前面加0补齐
            string::size_type L1,L2;
            int i;
            L1=str1.size();
            L2=str2.size();
            if (L1<L2) {
                for (i=1;i<=L2-L1;i++) str1="0"+str1;
            } else {
                for (i=1;i<=L1-L2;i++) str2="0"+str2;
            }
            int int1=0,int2=0; //int2 记录进位
            for (i=str1.size()-1;i>=0;i--) {
                int1=(int(str1[i])-'0'+int(str2[i])-'0'+int2)%10;
                int2=(int(str1[i])-'0'+int(str2[i])-'0'+int2)/10;
                str=char(int1+'0')+str;
            }
            if (int2!=0) str=char(int2+'0')+str;
        }
    }
    //运算后处理符号位
    if ((sign==-1)&&(str[0]!='0')) str="-"+str;
    return str;
}
string SUB_INT(string str1,string str2) {//高精度减法
    int sign=1; //sign 为符号位
    string str;
    int i,j;
    if (str2[0]=='-') {
        str=ADD_INT(str1,str2.erase(0,1));
    } else {
        int res=compare(str1,str2);
        if (res==0) return "0";
        if (res<0) {
            sign=-1;
            string temp =str1;
            str1=str2;
            str2=temp;
        }
        string::size_type tempint;
        tempint=str1.size()-str2.size();
        for (i=str2.size()-1;i>=0;i--) {
            if (str1[i+tempint]<str2[i]) {
                j=1;
                while (1) {//zhao4zhong1添加
                    if (str1[i+tempint-j]=='0') {
                        str1[i+tempint-j]='9';
                        j++;
                    } else {
                        str1[i+tempint-j]=char(int(str1[i+tempint-j])-1);
                        break;
                    }
                }
                str=char(str1[i+tempint]-str2[i]+':')+str;
            } else {
                str=char(str1[i+tempint]-str2[i]+'0')+str;
            }
        }
        for (i=tempint-1;i>=0;i--) str=str1[i]+str;
    }
    //去除结果中多余的前导0
    str.erase(0,str.find_first_not_of('0'));
    if (str.empty()) str="0";
    if ((sign==-1) && (str[0]!='0')) str ="-"+str;
    return str;
}
string MUL_INT(string str1,string str2) {//高精度乘法
    int sign=1; //sign 为符号位
    string str;
    if (str1[0]=='-') {
        sign*=-1;
        str1 =str1.erase(0,1);
    }
    if (str2[0]=='-') {
        sign*=-1;
        str2 =str2.erase(0,1);
    }
    int i,j;
    string::size_type L1,L2;
    L1=str1.size();
    L2=str2.size();
    for (i=L2-1;i>=0;i--) { //模拟手工乘法竖式
        string tempstr;
        int int1=0,int2=0,int3=int(str2[i])-'0';
        if (int3!=0) {
            for (j=1;j<=(int)(L2-1-i);j++) tempstr="0"+tempstr;
            for (j=L1-1;j>=0;j--) {
                int1=(int3*(int(str1[j])-'0')+int2)%10;
                int2=(int3*(int(str1[j])-'0')+int2)/10;
                tempstr=char(int1+'0')+tempstr;
            }
            if (int2!=0) tempstr=char(int2+'0')+tempstr;
        }
        str=ADD_INT(str,tempstr);
    }
    //去除结果中的前导0
    str.erase(0,str.find_first_not_of('0'));
    if (str.empty()) str="0";
    if ((sign==-1) && (str[0]!='0')) str="-"+str;
    return str;
}
string DIVIDE_INT(string str1,string str2,int flag) {//高精度除法。flag==1时,返回商; flag==0时,返回余数
    string quotient,residue; //定义商和余数
    int sign1=1,sign2=1;
    if (str2 == "0") {  //判断除数是否为0
        quotient= "ERROR!";
        residue = "ERROR!";
        if (flag==1) return quotient;
        else         return residue ;
    }
    if (str1=="0") { //判断被除数是否为0
        quotient="0";
        residue ="0";
    }
    if (str1[0]=='-') {
        str1   = str1.erase(0,1);
        sign1 *= -1;
        sign2  = -1;
    }
    if (str2[0]=='-') {
        str2   = str2.erase(0,1);
        sign1 *= -1;
    }
    int res=compare(str1,str2);
    if (res<0) {
        quotient="0";
        residue =str1;
    } else if (res == 0) {
        quotient="1";
        residue ="0";
    } else {
        string::size_type L1,L2;
        L1=str1.size();
        L2=str2.size();
        string tempstr;
        tempstr.append(str1,0,L2-1);
        for (int i=L2-1;i<L1;i++) { //模拟手工除法竖式
            tempstr=tempstr+str1[i];
            tempstr.erase(0,tempstr.find_first_not_of('0'));//zhao4zhong1添加
            if (tempstr.empty()) tempstr="0";//zhao4zhong1添加
            for (char ch='9';ch>='0';ch--) { //试商
                string str;
                str=str+ch;
                if (compare(MUL_INT(str2,str),tempstr)<=0) {
                    quotient=quotient+ch;
                    tempstr =SUB_INT(tempstr,MUL_INT(str2,str));
                    break;
                }
            }
        }
        residue=tempstr;
    }
    //去除结果中的前导0
    quotient.erase(0,quotient.find_first_not_of('0'));
    if (quotient.empty()) quotient="0";
    if ((sign1==-1)&&(quotient[0]!='0')) quotient="-"+quotient;
    if ((sign2==-1)&&(residue [0]!='0')) residue ="-"+residue ;
    if (flag==1) return quotient;
    else         return residue ;
}
string DIV_INT(string str1,string str2) {//高精度除法,返回商
    return DIVIDE_INT(str1,str2,1);
}
string MOD_INT(string str1,string str2) {//高精度除法,返回余数
    return DIVIDE_INT(str1,str2,0);
}
int main() {
    string s1,s2,s3,s4;
    int i;

    s4="0";

    s3="1";
    for (i=0;i<1002;i++) s3+="0";

    s1="1";
    s2="1";

    s4=ADD_INT(s4,DIV_INT(s3,s1));
    s4=ADD_INT(s4,DIV_INT(s3,s1));

    for (i=2;i<451;i++) {//因为450!是一个1001位数
        s2=ADD_INT(s2,string("1"));
        s1=MUL_INT(s1,s2);
        s4=ADD_INT(s4,DIV_INT(s3,s1));
    }

    cout<<s4<<endl;

    return(0);
}
//271828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642742746639193200305992
//181741359662904357290033429526059563073813232862794349076323382988075319525101901157383418793070215408914993488416750924
//476146066808226480016847741185374234544243710753907774499206955170276183860626133138458300075204493382656029760673711320
//070932870912744374704723069697720931014169283681902551510865746377211125238978442505695369677078544996996794686445490598
//793163688923009879312773617821542499922957635148220826989519366803318252886939849646510582093923982948879332036250944311
//730123819706841614039701983767932068328237646480429531180232878250981945581530175671736133206981125099618188159304169035
//159888851934580727386673858942287922849989208680582574927961048419844436346324496848756023362482704197862320900216099023
//530436994184914631409343173814364054625315209618369088870701676839642437814059271456354906130310720851038375051011574770
//4171898610687396965521267154688957035035174
沈万三gz 2013-07-31
  • 打赏
  • 举报
回复
楼上说的方法好像很复杂,这样做的话,程序操作会很麻烦,而且受到很多限制。 我看别人的代码用的是数据结构代替数字,具体的方法没看懂,现在就想把函数出入口看懂,再封装一下拿来用
课程亮点: 从无到有、手把手教你编写CA/TA,快速上手,快速部署项目标准的开发,开发一套CA/TA,可部署到不同的TEE OS上。受益人群: 汽车行业主机厂、tier1、SOC芯片公司的安全部门同事手机行业,ODM/OEM、SOC芯片公司的安全部门同事学生课程收益: 熟悉CA/TA开发的步骤和流程。快速上手,快速搭建自己开发环境。熟悉各类TEE、基于各类TEE的CA/TA开发步骤。搭建自己的安全平台熟悉各类常规安全应用熟悉tee密码学算法、tee存储  课程大纲  Hello大家好,上架一门新的视频课程,课程主要包含两大部分,第一部分搭建环境,第二部分从无到有的编写代码。带领大家手把手编写。 具体大纲如下:(1)qemu v8环境搭建- 搭建一个qemu_v8的环境,用于跑BL1-->BL2-->BL31-->BL32-->BL33-->Linux kernel;- 直接使用已搭建好的镜像- 工程使用以及说明(2)CA/TA开发编程实践从无到有编写代码,已完成的大纲如下:- 2秒钟快速编写(clone)一组CA/TA程序- 安全存储详解以及代码示例- CA到TA双向传参数的四种方式(value、temref、memref),区别?优缺点?- 对称密码学算法aes的使用,CBC/ECB/CTR/XTS分组密码的使用,加密解密,pending等- aeskey的操作,如何随机生成aeskey(TEE_GenerateKey),objectHandle和aesbuf有什么区别? 如何将handle- 认证加密算法,如aes-GCM的使用- 非对称密码学算法RSA的使用,包括加密、解密、签名、验签- RSA key的处理,包含如何生成RSA KEY,rsakey object如何转换成可见的数组,如何转换der,如何转换pem,反向又如何转换- ECC/ECDSA的使用- 国密sm2 sm3 sm4的使用.  其中sm4包含加密、解密、签名、验签等- encode和decode的实现- TA属性的定制以及API的使用- 数字摘要  SHA1 sha224 sha256 sha384 sha512等- 消息认证码 HMAC- TEE侧获取时间的函数有哪些(TEE_GetSystemTime、TEE_GetREETime),有什么区别?分别是怎样使用的? - 如何获取随机数(TEE_GenerateRandom)?- TA调用TA的示例和演示后续可能继续补充的如下(也欢迎大家提需求):- multi-session和multi-instance的使用- CA LOGIN flag的使用 

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧